Converting DynamoDB JSON document to JSON object in Java - java

I am reading the backup DynamoDB S3 bucket which has format for DynamoDB JSON.
I am trying to convert it into a normal JSON without the AttributeValue.
Original String
{
"id": {
"s": "someString"
},
"name": {
"b": "someByteBuffer"
},
"anotherId": {
"s": "someAnotherString"
},
"version": {
"n": "1"
}
}
Trying to convert to
{
"id": "someString",
"name": "someByteBuffer",
"anotherId": "someAnotherString",
"version": "1"
}
There are many answers which I referred to, but it doesn't convert into normal JSON, it gives me back the same JSON.
Here is what I tried:
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(inputJsonString);
final JacksonConverter converter = new JacksonConverterImpl();
Map<String, AttributeValue> map = converter.jsonObjectToMap(jsonNode);
Item item = ItemUtils.toItem(map);
Gson gson = new Gson();
System.out.println(gson.toJson(item.asMap()));
Also, when I was debugging, I wasn't able to create the Map properly. Map would contain key as "id", value as AttributeValue, but the AttributeValue would contain the string inside its own Map<String, AttributeValue> instead of inside String s
I feel I am missing something while creating the Map. Any pointers?
References on Stackoverflow:
Link 1
Link 2

What you're describing as the result sounds correct. If you look at the original JSON string, you have a list of key:value pairs where each value is another list of key:value pairs (length 1, but still a list).
To convert this to a single list of key:value pairs you need to write a map-reduce type of loop. Basically iterate the first map, take the key, then, from the second map (which is the value for the key you just recorded), just take the first entry's value (AttributeValue) and add that key:value pair into a new map (Map<String, AttributeValue>, which you define before the loop). That map you can then convert to JSON and it will result in the JSON string that you were expecting.
Hope that helps!

Related

Json To Dto Class for map of String, String but same key allowed repeatedly

Requirement is in json, there will be map of string & string but multiple key having same value should be allowed.
Something like this
{
"src": "A",
"dest": "B",
"interStoreType": {
"C1": "C1",
"C2": "C2",
"C2": "C3",
"C3": "C3"
}
}
This value is in String in one db column, So, I use objectmapper to convert it to a Dto object.
By defult if I use map, it will be [C1:C1, C2:C3, C3:C3], it will take last value
So, tried with Multimap (guava), MultiValuedMap(apache commons collection), there also it is giving same value as of what Map gives.
Other ways are there like adding array in value part or join with delimeter.
But, I want to know the reason why object mapper is not creating multiple record for same key.
You can't have duplicate keys in a map. A MultiValuedMap is a map of lists, so it is also a map, so it cannot have duplicate keys either.
Try to express your JSON like this:
{
"src": "A",
"dest": "B",
"interStoreType": {
"C1": ["C1"],
"C2": ["C2","C3"],
"C3": ["C3"]
}
}

In java8 Collectors.toMap, keyMapper value should come from another constant map's key

I have a situation like :
In my project i am using spring boot with spring data.So right now i have to filter my main entity on various fields. Fields and their value are coming in json format in request body in post call like this.
{
"filters": [
{
"field": "ownerUiids",
"terms": "1,2"
},
{
"field": "key",
"terms": "a"
},
{
and many more
}
],
"sortBy": "wwww"
}
I have a pojo class to convert this json into java.and in that pojo class contain list of fields coming from json.
I converted this list into map of field and its value as key and value like :
Map<String,String> filterMap =
request.getFilters().stream().collect(Collectors.toMap(Filter::getField,
Filter::getTerms));
So my problem starts here the name of field in json doesnot match with my column name in db, so while making criteria api the actual column name doesnot appear in query making.
To solve this problem i made constant static map with key as a json field and value is actual column name corresponding to that field like :
public static final Map<String, String> myMap = Collections.unmodifiableMap(
new HashMap<String, String>() {{
put("ownerUiids", "ownerUIID");
put("key", "keyValue");
}});
So when i am making filterMap i need the key should be value of constant myMap i.e instead of Filter::getField if i can do myMap.getKey(Filter::getField). But right now i am not able to do like this.
Map<String,String> filterMap =
request.getFilters().stream().collect(Collectors.toMap(myMap.getKey(Filter::getField),
Filter::getTerms));
After this thing i have my map of column name and its value which is my current req. and also solve my problem.
Please help me in this sol. or if you have better approach than this then that is also appreciable.
You can't use method reference like that. Try this:
Map<String,String> filterMap =
request.getFilters().stream()
.collect(Collectors.toMap(f -> myMap.get(f.getField()),
Filter::getTerms));
for the reason create dto class and format raw data
1 : create dto and write converter method in dto class
List<Dto> dtos = request.getFilters().stream().map(Dto::convert).collect(Collectors.toList())
2 : and now create map
Map<String,String> filterMap = dtos.stream().collect(Collectors.toMap(Dto::getField,Dto::getTerms))

Java Jackson Serialize JSON to HashTable

I am trying to serialize a list of JSON blobs and put certain keys into a HashTable during the serialization. Here is an example of my JSON:
[
{
"name": "sally",
"id": 1,
"eye_color": "green"
},
{
"name": "jack",
"id": 2,
"eye_color": "blue"
},
{
"name": "jane",
"id": 3,
"eye_color": "brown"
}
]
What I am looking for specifically is a POJO (or set of POJOs) which can serialize the above JSON like so with Jackson assuming the above JSON is in a file called above_json.json:
MyPOJO pojo = objectMapper.readValue(new File("above_json.json"), MyPOJO.class);
I want the result of the serialization to give me a HashTable (or an Object which encapsulates the HashTable) where the HashTable key is the value of name and the Hashtable value is the value of the corresponding id above.
Assuming we serialized the above JSON in this fashion, I would want to access the HashTable like so:
myTable.get("jane")
result: 3
myTable.get("jack")
result: 2
myTable.get("Jill")
result: null
I know how to serialize basic JSON with Jackson. I have an example like below:
JSON Input:
"Parameter":{
"Name":"Parameter-Name",
"Value":"Parameter-Value"
}
POJO to serialize above simple JSON:
public class Parameter {
#JsonProperty("Name")
public String name;
#JsonProperty("Value")
public String value;
}
But obviously this type of setup does not put the results into a HashTable. I need a POJO like what I have in this example which will serialize JSON directly into a HashTable
I don't think that is possible.
You serialize this json into a list of pojos, and have a utility function to generate the hashtable in the way you desire from the list of pojos.
Create a POJO for holding the properties you are interested in.
#JsonIgnoreProperties(ignoreUnknown = true)
private static class MyPOJO {
#JsonProperty("name")
private String name;
#JsonProperty("id")
private Integer id;
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
Deserialize the contents of the file into List<MyPOJO>
List<MyPOJO> myPOJO = mapper.readValue(new File(".."), new TypeReference<List<MyPOJO>>(){});
Stream the contents of the map to construct a map whose key is the name and value is the id.
Map<String, Integer> map = myPOJO.stream()
.collect(Collectors.toMap(MyPOJO::getName, MyPOJO::getId));
First of all, you probably don't want to use a HashTable, as it's considered to be an obsolete type (see here).
Either use a HashMap or if you want thread safety, a ConcurrentHashMap or a thread-unsafe Map backed by Collections.synchronized[...] and referenced to within synchronized statements.
Secondly, you can use a TypeReference to de-serialize as your desired type.
Finally, your JSON's syntax is incorrect: it starts with a square bracket ([) and ends with a curly bracket (}), which is technically unparseable.
Assuming you want an array of Maps here (e.g. HashMap<String, String>[]), here is some suitable code, provided you replace the last curly bracket with a square one:
// the map array
Map<String, String>[] map = null;
map = om.readValue(yourFile, new TypeReference<HashMap<String, String>[]>() {});
// prints the de-serialized contents
System.out.println(Arrays.toString(map));
Edit
Since you have now edited your JSON to remove the first square bracket and replace it with a curly bracket, no you can't parse as a Map as is.
Edit 2
Since you have now re-edited your JSON to feature square brackets once again instead of curly brackets in the wrapping object, you can once again de-serialize as a Map[]. Until the next edit, I guess...

java jsonobject "value" and "num"

when using the javax json ObjectBuilder to build json, the output json string contains "value" and "num" in the json string. my web service is throw serialization error when the json contains "value" and "num". any one know why the output have "value" and "num"?
example:
JsonObject addProductRequest = Json.createObjectBuilder()
.add("OrderID", orderId)
.add("Product", productId)
.add("Quantity", qty)
.add("access_token", access_token)
.build();
output:
{
"OrderID": {
"num": 15498
},
"ProductID": {
"num": 20
},
"Quantity": {
"num": 1
},
"access_token": {
"value": "1f6c689d-6956-4f8e-b259-9030d57bec4b"
}
}
when I switch to using google.gson.JsonObject, the output dont have the "value" and "num" string, which my web service accepts and every thing seems to work fine.
example
com.google.gson.JsonObject addProductRequest = new com.google.gson.JsonObject();
addProductRequest.addProperty("OrderID", orderId);
addProductRequest.addProperty("Product", productId);
addProductRequest.addProperty("Quantity", qty);
addProductRequest.addProperty("access_token", access_token);
output:
{ "OrderID": 15499, "Product": 20, "Quantity": 1, "access_token": "3241cfd4-7b6c-4eac-b2bb-9b2b0c780831"}
Rest Assured seems to use Gson to serialize POJOs (which is what you should be using as response entities) to the response body.
Gson doesn't know anything about javax.json. The implementation of javax.json that you are using basically has this format for its JsonObject:
private static final class JsonObjectImpl extends AbstractMap<String, JsonValue> implements JsonObject {
private final Map<String, JsonValue> valueMap; // unmodifiable
Since this is a Map, Gson uses special serializing, iterating through its entrySet and using each Entry as a JSON key-value pair (within a JSON object).
In this case, the entrySet returns
#Override
public Set<Entry<String, JsonValue>> entrySet() {
return valueMap.entrySet();
}
where the valueMap contains all the values you added with add in your builder. For example, for
.add("OrderID", 1)
it will have added an entry with the String key OrderID and the JsonValue value of
// Optimized JsonNumber impl for int numbers.
private static final class JsonIntNumber extends JsonNumberImpl {
private final int num;
Notice the num field.
So Gson will now see a value of this JsonIntNumber type. It considers it a POJO and so serializes it as a JSON object with its fields as key-value pairs. It therefore produces
{
"num": 15498
}
com.google.gson.JsonObject is a known type to Gson. It knows that it is special and not a custom POJO type. It can therefore write it directly, instead of having to serialize it further.
This is similar to a question which I answered here:
Returning JsonObject using #ResponseBody in SpringMVC

Android: Handling json objects that can be a string or array

Ran into a situation where am not sure how to handle it.
I have json data that comes from a server; for example:(am just posting part of the json, so, yes, the json is valid)
"wall_id": 889149,
"poster_image_thumbnail": "http:\/\/www.mface.me\/images\/avatar\/thumb_62441559ddb1dda7513d0f94.jpg",
"post_type": "profile",
"post_content": [{
"text": "",
"images_count": 1,
"images": ["https:\/\/fbcdn-sphotos-a-a.akamaihd.net\/hphotos-ak-ash4\/227408_475848819113499_663318592_n.jpg"]
}]
Created a class to store this json data
public class feedFormat{
Integer wall_id;
String poster_image_thumbnail;
String post_type;
String post_content;
}
There are times when post_content can be empty or an array as the example above. I have declared post_content as String in feedFormat. This is obviously throwing a cast exception (Converting array to string?).
I was expecting JSONObject to read it as a string and later convert it into an array from there, but does'nt seem to go that way.
How can i dynamically handle a string or an array? if it is an array, i need to break it down.
I am porting this app from IOS to android, there is a "id" object in IOS that can be of any class. I check if the class is a NSSTring or NSArray and take it from there. Here in Java, am not sure how to handle it.
Any suggestions are highly appreciated
If your JSON array is empty, it will be like that :
"post_content": []
It will then remain an array, with the particularity of being 0-sized.
Then I suggest you parse directly your JSON array into a appropriate data structure, whatever the size, like an ArrayList> for example. You will then be able to go through all the items of your JSON array, and for each item, add a new HashMap in your arraylist. Every hashmap will contain there pairs of key values.
However, if I understand well your JSON, it seems that it will be always an array of three elements, the third element being itself a array, which size is given bu the attribute images_count. This is not very good, your JSON structure should be :
"post_content": {
"text": "",
"images": [
"https://fbcdn-sphotos-a-a.akamaihd.net/hphotos-ak-ash4/227408_475848819113499_663318592_n.jpg"
]
}
Since images is an array, you can easily get its size.
JSONObject has functions called has(String key) which checks if there is a mapping for a key and isNull(String key) which checks if a particular key is null. Use these to check the key before reading.
public class FeedFormat{
Integer wall_id;
String poster_image_thumbnail;
String post_type;
JSONArray post_content;
}
feedFormat toto = new feedFormat();
toto.post_content = yourJsonObject.getJsonArray("post_content");
This is the easiest way to do what you want. Another way is to create another class.
public class FeedFormat{
Integer wall_id;
String poster_image_thumbnail;
String post_type;
ArrayList<PostContent> post_content = new ArrayList<PostContent>();
}
public class PostContent {
String text;
Integer imageCount;
ArrayList<String> images = new ArrayList<String>();
}
With that you can handle each post content into specific object instead of use JSONObject / JSONArray.
you can check like this jsonobject.has("post_content")
if(jsonobject.has("post_content")) {
/// read array and do remaining stuff
}else {
// if not read another strings and put post_content as null.
}
You can use something like this:
String data= "wall_id": 889149,
"poster_image_thumbnail": "http:\/\/www.mface.me\/images\/avatar\/thumb_62441559ddb1dda7513d0f94.jpg",
"post_type": "profile",
"post_content": [{
"text": "",
"images_count": 1,
"images": ["https:\/\/fbcdn-sphotos-a-a.akamaihd.net\/hphotos-ak-ash4\/227408_475848819113499_663318592_n.jpg"]
}]
JSONArray jArray=data.getJSONArray("post_content");
for(int i=0; i<jArray.length(); i++)
{
JSONObject jObj=jArray.getJSONObject(i);
String text=jObj.getString("text");
int images_count=jObj.getInt("images_count");
String images=jObj.getInt("images");
}

Categories

Resources