Java dynamic Map<String, Map> merging to be converted to a JSON - java

I'm using a Map<String, Map> resultMap having values like this:
[
{main={group={street={cnt=Burundi, zip=123}, code=asd, subtype={OrgType=1,2}}}},
{main={info={text=bbb}}},
{main={group={subId=5, attrib={attribId=1,2}}}}
]
I have to create a JSON out of those Maps that should look like this:
{ "main": [
{
"group": {
"street": {
"cnt": "Burundi",
"zip": "123"
},
"code": "asd",
"subtype": {
"OrgType": "1,2"
},
"subId": "5",
"attribId": "1,2"
},
"info": {
"text": "bbb"
}
}
]
}
Any idea how could I merge those Maps doing a GSON.toJson(resultMap); to obtain this JSON ?
I tried to merge the Map
public String produceJsonFromMap(Map<String, Map> initialMap) {
Map<String, Object> resultMap = new HashMap<>();
for(Map map: initialMap.values()) {
resultMap.putAll(map);
}
return GSON.toJson(resultMap);
}
But this overwrites my previous maps and I don't know how can I obtain the desired merged map...

Related

Java Jackson Deserialization

I struggled a while trying to find way to deserialize this following structure into java object using fasterxml.jackson.
Obviously the "NewYork" and "Boston" are the keys, not an schema I must unmarshall into map
Map<String, Object> jsonMap = mapper.readValue(jsonString,
new TypeReference<Map<String,Object>>(){});
But the jsonMap return is LinkedHashMap, with key is "NewYork", value is another LinkedHashMap. In the second inner map, the key is "schedules", and value are list of LinkedHashMap. The third inner map, the key, value are
"date": "2020-10-31",
"flightNo": "UA110",
"depart": "17:30PM"
What I want is java model like this
public class FlightInfo {
Map<String, List<Schedule>> info;
}
I did some search, thinking about JsonNode, Json node must know the property name, in my case, NewYork and Boston are not determined.
I could not find way to do that.
{
"NewYork": {
"schedules": [
{
"date": "2020-10-31",
"flightNo": "UA110",
"depart": "17:30PM"
},
{
"date": "2020-11-01",
"flightNo": "UA230",
"depart": "18:30PM"
}
]
},
"Boston": {
"schedules": [
{
"date": "2020-11-01",
"flightNo": "AM110",
"depart": "08:00AM"
},
{
"date": "2020-11-01",
"flightNo": "CA230",
"depart": "10:30AM"
}
]
}
}
Thanks
The JSON string is not adapt to your expected data model Map<String,Object> or Map<String, List<Schedule>>. Actually there are two level mappings, NewYork -> schedules -> List Of Schedule
So we should use the below TypeReference with two level Map to do deserialize
mapper.readValue(jsonString, new TypeReference<Map<String, Map<String, List<Schedule>>>>(){});
Certainly, if you persist to use one level mapping, you could modify the data, like the following. And thus we could use a simple version TypeReference<Map<String, List<Schedule>>>
{
"NewYork": [
{
"date": "2020-10-31",
"flightNo": "UA110",
"depart": "17:30PM"
},
{
"date": "2020-11-01",
"flightNo": "UA230",
"depart": "18:30PM"
}
],
"Boston": [
{
"date": "2020-11-01",
"flightNo": "AM110",
"depart": "08:00AM"
},
{
"date": "2020-11-01",
"flightNo": "CA230",
"depart": "10:30AM"
}
]
}

How to add the name before the array in the array object itself in a JSON response?

I am consuming an external web service and receiving a JSON response. In this response, there is an object "entities" containing multiple arrays in it, with a name before each array.
I want to add the name before the array in the array object itself.
For example this is the original response:
{
"entities": {
"entity": [
{
"confidence": 1,
"value": "user",
"type": "value"
},
{
"confidence": 1,
"value": "insurance form",
"type": "value"
}
],
"ui_page_step": [
{
"confidence": 1,
"value": "step 1",
"type": "value"
}
],
"userrole_ano": [
{
"confidence": 0.96535832252792,
"value": "anonymous user"
}
]
}
}
I need to convert it to:
{
"entities": {
"entity": [
{
"name": "entity",
"confidence": 1,
"value": "user",
"type": "value"
},
{
"name": "entity",
"confidence": 1,
"value": "insurance form",
"type": "value"
}
],
"ui_page_step": [
{
"name": "ui_page_step",
"confidence": 1,
"value": "step 1",
"type": "value"
}
],
"userrole_ano": [
{
"name": "userrole_ano",
"confidence": 0.96535832252792,
"value": "anonymous user"
}
]
}
}
How can I convert the original response to the desired one in Java?
Here is a (one of several possible) solutions:
It uses Jackson library to parse the Json into a java Map that is (relatively) easier to navigate and modify than JSONObject.
the method putCollectionNamesInsideEntries() assumes one root "entities" entry that has several collections as values. it iterates over all of them, adding "name" entry with name of collection.
the map is serialized back to Json (and sent to System.out)
import java.io.*;
import java.nio.file.*;
import java.util.*;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonTest
{
public static void main(String[] args) {
try (InputStream is = Files.newInputStream(Paths.get("C:/temp/test.json"))) {
ObjectMapper mapper = new ObjectMapper();
// deserialize json into map
Map<String, Object> map = (Map<String, Object>)mapper.readValue(is, Map.class);
putCollectionNamesInsideEntries(map);
// serialize map into json
mapper.writeValue(System.out, map);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void putCollectionNamesInsideEntries(Map<String, Object> map) {
// get root "entities" entry
Map<String, Object> entitiesMap = (Map<String, Object>)map.get("entities");
for (Map.Entry<String, Object> entitiesEntry : entitiesMap.entrySet()) {
// iterate over collection entries
if (entitiesEntry.getValue() instanceof Collection) {
Collection coll = (Collection)entitiesEntry.getValue();
// iterate over entries in collection
for (Object collEntry : coll) {
if (collEntry instanceof Map) {
// add "name" with ame of collection (key entry under "entries")
((Map<String, Object>)collEntry).put("name", entitiesEntry.getKey());
}
}
}
}
}
}

How do I insert a Json node into another one in Java?

I have one Json node:
{
"name":
{
"first": "Tatu",
"last": "Saloranta"
},
"title": "Jackson founder",
"company": "FasterXML"
}
I have another Json node (the one which I want to insert):
{
"country": "My country",
"hobbies": "some hobbies"
}
I want my resulting node to be:
{
"additional info":
{
"country": "My country",
"hobbies": "some hobbies"
},
"name":
{
"first": "Tatu",
"last": "Saloranta"
},
"title": "Jackson founder",
"company": "FasterXML"
}
How do I do that in Java? Here is my java code:
private final static ObjectMapper JSON_MAPPER = new ObjectMapper();
JsonNode biggerNode = parseTree(someObject);
JsonNode nodeToBeInsertede = JSON_MAPPER.valueToTree(anotheObj);
//I want to do something like this:
//biggerNode.put("additionalInfo", nodeToBeInsertede)
Instead of JsonNode read a Map and use standard Map.put() to modify the bigger object:
ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
TypeReference<Map<String, Object>> type = new TypeReference<>() {};
Map<String, Object> biggerMap = mapper.readValue(biggerJson, type);
Map<String, Object> smallerMap = mapper.readValue(smallerJson, type);
biggerMap.put("additional_info", smallerMap);
String outJson = mapper.writeValueAsString(biggerMap);
System.out.println(outJson);
will output:
{
"name" : {
"first" : "Tatu",
"last" : "Saloranta"
},
"title" : "Jackson founder",
"company" : "FasterXML",
"additional_info" : {
"country" : "My country",
"hobbies" : "some hobbies"
}
}

Naming the ArrayList Dynamically in Java

Suppose I have a json as
{
"data": {
"json": [
{
"value": [
"john","joy"
],
"key": "Names"
},
{
"value": [
"25A",
"26B"
],
"key": "john"
},
{
"value": [
"27A",
"28B"
],
"key": "joy"
}
]
}
}
I want to do create a Dynamic ArrayList names for each values as shown below
for(String name:Names){
//create a dynamic arraylist from the names here like
// ArrayList<String> joy= ..........
}
Can Anyone help me with this please?
Maybe use
Map<String, List<String>> map = new HashMap<String, List<String>>();
map.put("arrayname", new ArrayList<String>());

Use gson to convert json that should be array of objects, but isn't

{"myContainer" :
{ "couldBeAnything" : [
{"id":1, "name":"sb", "category":"couldBeAnything"},
{"id":2, "name":"bs", "category":"couldBeAnything"}
],
"somethingElse" : [
{"id":1, "name":"sdsa","category":"somethingElse"},
{"id":2, "name":"ve","category":"somethingElse"}
]
},
"id" : 0
}
So far I have :
Type myContainerType = new TypeToken<MyContainer>(){}.getType();
MyContainerType myContainerType = gson.fromJson(myJson.getValue(), myContainerType);
Where
public class MyContainer {
private int id;
private Map<String, List<Foo>> foo; // and foo has id, name, category
The result, no errors, a populated id field, but just a null map
I think the json is wrong for the structure Map<String, List<Foo>>. When you say map you need not enclose each key-value with {. Just put the whole key values in one {} and seprate with commas. eg
{
"myContainer": {
"couldBeAnything": [
{
"id": 1,
"name": "sb",
"category": "couldBeAnything"
},
{
"id": 2,
"name": "bs",
"category": "couldBeAnything"
}
],
"somethingElse": [
{
"id": 1,
"name": "sdsa",
"category": "somethingElse"
},
{
"id": 2,
"name": "ve",
"category": "somethingElse"
}
]
},
"id": 0
}
With this json it works perfectly
public static void main(String[] args){
String json = "{\"myContainer\":{\"couldBeAnything\":[{\"id\":1,\"name\":\"sb\",\"category\":\"couldBeAnything\"},{\"id\":2,\"name\":\"bs\",\"category\":\"couldBeAnything\"}],\"somethingElse\":[{\"id\":1,\"name\":\"sdsa\",\"category\":\"somethingElse\"},{\"id\":2,\"name\":\"ve\",\"category\":\"somethingElse\"}]},\"id\":0}";
Map<String, List<Foo>> obj = new HashMap<String, List<Foo>>();
Gson gson = new Gson();
obj = gson.fromJson(json, obj.getClass());
System.out.println(obj);
}
Output
{id=0.0, myContainer={couldBeAnything=[{id=1.0, name=sb, category=couldBeAnything}, {id=2.0, name=bs, category=couldBeAnything}], somethingElse=[{id=1.0, name=sdsa, category=somethingElse}, {id=2.0, name=ve, category=somethingElse}]}}
The issue with your approach was the naming of the field foo. Your json contains the Map<String, List<Foo>> name as myContainer. So modify your container class like below and it will work fine :)
public class MyContainer {
private int id;
private Map<String, List<Foo>> myContainer;
}
Now this will work
Type myContainerType = new TypeToken<MyContainer>(){}.getType();
MyContainer myContainer = gson.fromJson(json, myContainerType);
System.out.println(myContainer);

Categories