Putting a value in DynamoDB table with attributes as set of objects - java

I need to persist an attribute in DynamoDB Table, whhere attribute is Set<Some Class>.
Basically I need to put that attribute in Map<String,AttributeValue>.
For generation situation we generally do
Map<String,AttributeValue> itemsInTable = new HashMap<String, AttributeValue>();
itemsInTable.put("Id", new AttributeValue("123"));
Now suppose I have a Set<Info> where Info is a class.
How to put that kind of Attribuute?
and also if the attribute Value is a list ??

After two three days of research I just found there is no direct way to put something like set<Info> in DynamoDB using this kind of Notation.
Map<String,AttributeValue> itemsInTable = new HashMap<String, AttributeValue>();
itemsInTable.put("Id", new AttributeValue("123"));
But we can opt some middle way to convert the Object to JSONObject or JSONString and put in Map<String,AttributeValue> by using
Set<String> set = new HashSet<String>();
Map<String,AttributeValue> itemsInTable = new HashMap<String, AttributeValue>();
itemsInTable.put("Id", new AttributeValue().withSS(set));
To convert object to jsonString we can take help of jackson library.
import this:
import zaaa.org.codehaus.jackson.map.ObbjectMapper
Define ObjectMapper
private final ObjectMapper jacksonObjectMapper = new ObjectMapper();
Now suppose class is Container and its corresponding Object is `container'
Now the main job is to convert it into jsonString which can be easily done by using writevalueAsString function.
String jsonString = jacksonObjectMapper.writeValueAsString(container)
Now we have jsonString, we can easily convert it to JSONObject or JSONArray whenever needed.
I solved my issue by using this way.

Related

How can i add additional field to each object in array node using jackson java?

i have list of masters that have two fields that are name and rating and after serialization to array node i need to add one more field to each object
for example i have json
[{"masterName":"Bruce","rating":30},{"masterName":"Tom","rating":25}]
and i have list of servisec in json format that look like that
[{"masterName":"Bruce","services":["hair coloring","massage"]},{"masterName":"Tom","services":["hair coloring","haircut"]}]
i need it to looks something like that
[{"masterName":"Bruce","rating":30,"services":"hair coloring,massage"},{"masterName":"Tom","rating":25,"services":"hair coloring, haircut"}]
How can do it by using jackson?
I would approach it this way. Since you want to use Jackson.
First of all, I would extend the Master class by adding the services (which seems to be an array with Strings).
So the class would look something like this:
public class Master
{
private String masterName;
private int rating;
private List<String> services = new ArrayList<>(); // THE NEW PART
// Whatever you have else in your class
}
Then you could get your JSON array, I am supposing that it comes as a String for simplicity. Serialize this array in an array with Master objects and then you can add the services as said above.
e.g.
String yourJsonString = "[{\"masterName\":\"Bruce\",\"rating\":30},{\"masterName\":\"Tom\",\"rating\":25}]";
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
List<Master> theListOfMasters = new ArrayList<>();
// Read them and put them in an Array
Master[] mastersPlainArr = mapper.readValue(yourJsonString, Master[].class);
theListOfMasters = new ArrayList(Arrays.asList(mastersPlainArr));
// then you can get your masters and edit them..
theListOfMasters.get(0).getServices.add("A NEW SERVICE...");
// And so on...
// Then you can turn them in a JSON array again:
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(theListOfMasters);

accessing keys/values in JSONObject in java

In java I have the following code:
import org.json.JSONObject;
JSONObject obj = new JSONObject();
obj.put("firstKey", new JSONObject());
Now in the new object corresponding to the key "firstKey", I want to start inserting new key-value pairs, but I'm not sure how to do this. I've tried oppJSON.get("firstKey").put("one","two"); but this doesn't work - does anyone have any ideas?
JSONObject have specific get methods like getString, getInt, getDouble etc. In your case, you need getJSONObject
oppJSON.getJSONObject("firstKey").put("one","two");
Class JSONObject implements a Map without generics. So while you can use Map<String, String>, JSONObject is the equivalent of Map<Object, Object>. Everything pulled out of it using get has to be cast to its type.
Try ((JSONObject)obj.get("firstKey")).put("one", "two")

Jackson Unmarshall custom object instead of LinkedHashMap

I have a Java object Results:
public class MetaData {
private List<AttributeValue<String,Object>> properties
private String name
...
... getters/setters ...
}
The AttributeValue class is a generic key-value class. It's possible different AttributeValue's are nested. The (value) Object will then be another AttributeValue and so forth.
Due to legacy reasons the structure of this object cannot be altered.
I have my JSON, which I try to map to this object.
All goes well for the regular properties. Also the first level of the list is filled with AttributeValues.
The problem is the Object. Jackson doesn't know how to interpret this nested behavior and just makes it a LinkedHashMap.
I'm looking for a way to implement custom behavior to tell Jackson this has to be a AttributeValue-object instead of the LinkedHashMap.
This is how I'm currently converting the JSON:
ObjectMapper om = new ObjectMapper();
MetaData metaData = om.readValue(jsonString, new TypeReference<MetaData>(){});
And this is example JSON. (this is obtained by serializing an existing MetaData object to JSON, I have complete control over this syntax).
{
"properties":[
{
"attribute":"creators",
"value":[
{
"attribute":"creator",
"value":"user1"
},{
"attribute":"creator",
"value":"user2"
}
]
},{
"attribute":"type",
"value": "question"
}
],
"name":"example"
}
(btw: I've tried the same using GSON, but then the object is a StringMap and the problem is the same. Solutions using GSON are also welcome).
edit In Using Jackson ObjectMapper with Generics to POJO instead of LinkedHashMap there is a comment from StaxMan:
"LinkedHashMap is only returned when type information is missing (or if Object.class is defined as type)."
The latter seems to be the issue here. Is there a way I can override this?
If you have control over the serialization, try calling enableDefaultTyping() on your mapper.
Consider this example:
Pair<Integer, Pair<Integer, Integer>> pair = new Pair<>(1, new Pair<>(1, 1));
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(pair);
Pair result = mapper.readValue(str, Pair.class);
Without enableDefaultTyping(), I would have str = {"k":1,"v":{"k":1,"v":1}} which would deserialize to a Pair with LinkedHashMap.
But if I enableDefaultTyping() on mapper, then str = {"k":1,"v":["Pair",{"k":1,"v":1}]} which then perfectly deserializes to Pair<Integer, Pair<...>>.

How to convert Json string with key-value pair into string with only value

I actually converted my pojo data into json string this way,
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
String json=gson.toJson(user);
I got the json string but that is not the format i actually need, i got
json = {"userID":300,"userName":"asd","password":"s","enabled":1}
So, I want to convert Json string with key-value pair as below ,
{"userID":300,"userName":"asd","password":"s","enabled":1}
into Json string with only value (without key) as below
[300,"asd","s",1]
So I continue after your string json.
// lets deserialize your json string and get a hashmap
Type collectionType = new TypeToken<HashMap<String, Object>>(){}.getType();
HashMap<String, Object> hm = gson.fromJson(json, collectionType);
String finalJson = gson.toJson(hm.values());
// aand taa-daa!!
System.out.println(finalJson);
now finalJson is [300,"asd","s",1]
Edit: libraries are as following:
import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
You could whack the properties of the user into a List<Object> and then JSON that.
This would mean GSON made an JSON array out of the List and you would get what you want.
As this doesn't seem to make much sense as a use case you would have to do a bit of hardcoding - I don't think GSON can do this for you:
final List<Object> props = new LinkedList<>();
props.add(user.getId());
props.add(user.getUserName());
//etc
final String json=gson.toJson(props);
Could I ask why do you want to do that? If you retrieve that Json without key-value how you will know, for example, that 300 is his id and not his money property?
You can't difference between your properties and I don't really recommend it.
Anyway, the only way I find to do that, is to "break" your string manually, replacing your properties with blank values, like json.replace("\"userID\"", ""); and you should do it for every property.

Can't parse JSON array of arrays to LinkedHashMap in Jackson

I' m developing an Android REST client. We use JSON as data exchange format, so I use a Jackson parser. I get different Json responses from the server like simple arrays:
{"user_id":"332","user_role":"1"}
or something else. All these stuff I parse to LinkedHashMap<String, Object> and everything works perfectly but when I got this response from the server:
[ { "user_id":"352",
"user_role":"expert",
"name":"Test 12-18",
"description":"Test" },
{ "user_id":"263",
"user_role":"novice lab",
"name":"Tom's Desk",
"description":"Desk"}
]
I got null: {} after parsing.Here is my code where i use Jackson:
ObjectMapper mapParametersToJSON = new ObjectMapper();
String serverResponseBody = responseFromServer.getBody();
LinkedHashMap<String, Object> resultofOperation = new LinkedHashMap<String,
Object>();
TypeReference<LinkedHashMap<String,Object>> genericTypeReferenceInformation = new
TypeReference<LinkedHashMap<String,Object>>() {};
try {
resultofOperation = mapParametersToJSON.readValue(serverResponseBody,
genericTypeReferenceInformation);
So, why Jackson failed to parse this? How can I fix this?
Others have suggested the problem, but solutions are bit incomplete. If you need to deal with JSON Objects and Arrays, you can either bind to java.lang.Object, check the type:
Object stuff = objectMapper.readValue(json, Object.class);
and you will get either List or Map (specifically, ArrayList or LinkedHashMap, by default; these defaults can be changed).
Or you can do JSON trees with JsonNode:
JsonNode root = objectMapper.readTree(json);
if (root.isObject()) { // JSON Object
} else if (root.isArray()) { ...
}
latter is often more convenient.
One nice thing is that you can still create regular POJOs out of these, for example:
if (root.isObject()) {
MyObject ob = objectMapper.treeToValue(MyObject.class);
}
// or with Object, use objectMapper.convertValue(ob, MyObject.class)
so you can even have different handling for different types; go back and forth different representations.
The first JSON in your question is a map, or an object. The second is an array. You're not parsing an array, you're parsing a map.
You need to do something like this:
List<MyClass> myObjects = mapper.readValue(jsonInput, new TypeReference<List<MyClass>>(){});
Almost identical question with answer here.
In JSON the {"key": "value"} is Object and the ["this", "that"] is Array.
So, in case when you're receiving the array of objects you should use something like List<Map<Key, Value>>.
You are facing an error, because [] construction can't be translated into Map reference, only in List or array.
I would recommend do it something in this way:
ObjectMapper objectMapper = new ObjectMapper();
List<Map<String,String>> parsedResult = objectMapper.reader(CollectionType.construct(LinkedList.class, MapType.construct(LinkedHashMap.class, SimpleType.construct(String.class), SimpleType.construct(String.class)))).readValue(serverResponseBody);
//if you need the one result map
Map<String, String> resultMap = new LinkedHashMap<String, String>();
for (Map<String, String> map: parsedResult){
resultMap.putAll(map);
}

Categories