Parsing json with duplicate keys - java

I am trying to parse Json file which contains duplicate keys in java.I am using the method suggesteed in this answer Parsing a json which contains duplicate keys.
The approach works fine if I hard-code the Json but if I read it from a file,only the last duplicate key is read.Please Help as I want to read the Json from a file.Thanks in advance.
Code:
public class am {
public static void main(String args[]) throws Exception
{
JSONParser parser = new JSONParser();
Object obj = parser.parse(new FileReader("sample.json"));
JSONObject a=JSONObject.fromObject(obj);
JSONObject jsonObject=JSONObject.fromObject("{\n" +
" \"Data\": {\n" +
" \"A\": {\n" +
" \"B\": {\n" +
" \"C\": \"c\",\n" +
" \"D\": {}\n" +
" },\n" +
" \"E\": {\n" +
" \"F\": \"f\"\n" +
" },\n" +
" \"G\": {\n" +
" \"H\": \"h\"\n" +
" }\n" +
" },\"A\": {\n" +
" \"B\": {\n" +
" \"C\": \"x\",\n" +
" \"D\": {}\n" +
" },\n" +
" \"E\": {\n" +
" \"F\": \"y\"\n" +
" },\n" +
" \"G\": {\n" +
" \"H\": \"z\"\n" +
" }\n" +
" },\n" +
"
"\n" +
" }\n" +
"}");
System.out.println("Json objects are:::"+a);
System.out.println("Json objects are:::"+jsonObject);
}
}
Json File:
{
"Data": {
"A": {
"B": {
"C": "c",
"D": {}
},
"E": {
"F": "f"
},
"G": {
"H": "h"
}
},"A": {
"B": {
"C": "x",
"D": {}
},
"E": {
"F": "y"
},
"G": {
"H": "z"
}
},
}
}
Output:
Json objects are:::{"Data":{"A":{"B":{"C":"x","D":{}},"E":{"F":"y"},"G":{"H":"z"}}}}
Json objects are:::{"Data":{"A":[{"B":{"C":"c","D":{}},"E":{"F":"f"},"G":{"H":"h"}},{"B":{"C":"x","D":{}},"E":{"F":"y"},"G":{"H":"z"}}]}}

If you do not have a constraint to use external JSON library than you can use net.sf.json.JSONObject to parse your JSON string, It will accept JSON with the duplicate key. It will retain the duplicated values by storing them into arrays.
JSONObject jsonObject = JSONObject.fromObject( "{\"Data\": {\"A\": {\"B\": {\"C\": \"c\",\"D\": {}},\"E\": {\"F\": \"f\"},\"G\": {\"H\": \"h\"}},\"A\": {\"B\": {\"C\": \"x\",\"D\": {}},\"E\": {\"F\": \"y\"},\"G\": {\"H\": \"z\"}}}}" );
System.out.println( "net.sf.json.JSONObject: " + jsonObject );

You need to stringify your JSON object
a.toString()

Related

how to convert json to list/map with jackson

I encountered a piece of json as below:
{
"code": 1,
"msg": "query success",
"obj": {
"data": [
{
"name": "",
"value": {
"num": "89"
}
},
{
"name": "1",
"value": {
"num": "19"
}
},
{
"name": "2",
"value": {
"num": "6"
}
}
]
},
"success": true,
"duration": 523
}
I need name and num. How to convert it to a list of java.util.List<HashMap<String, String>> with Jackson?
You can use Jackson ObjectMapper with TypeReference ,
First you need to read it as Map<String,Object> then you can extract the name and num with Java.
you need to get the data from obj then for each item in the dataList you have to map it to a new HashMap as shown below
ObjectMapper objectMapper = new ObjectMapper ();
Map<String,Object> jsonMap = objectMapper.readValue(jsonData,new TypeReference<Map<String,Object>>(){});
List<Object> data = ((Map<String,Object>)jsonMap.get("obj")).get("data");
List<Map<String,String> result = data.stream()
.map(d->(Map<String,Object> d)
.map(d->{
Map<String,String> map = new HashMap();
map.put(d.get("name"),((Map<String,String>)d.get("value")).get("num"));
return map;
})
.collect(Collectors.toList());
However if you can create a class for the the data it will be bit easier.
Library Josson can do the job.
https://github.com/octomix/josson
Deserialization
Josson josson = Josson.fromJsonString(
"{" +
" \"code\": 1," +
" \"msg\": \"query success\"," +
" \"obj\": {" +
" \"data\": [" +
" {" +
" \"name\": \"\"," +
" \"value\": {" +
" \"num\": \"89\"" +
" }" +
" }," +
" {" +
" \"name\": \"1\"," +
" \"value\": {" +
" \"num\": \"19\"" +
" }" +
" }," +
" {" +
" \"name\": \"2\"," +
" \"value\": {" +
" \"num\": \"6\"" +
" }" +
" }" +
" ]" +
" }," +
" \"success\": true," +
" \"duration\": 523" +
"}");
Transformation
JsonNode node = josson.getNode("obj.data.map(name::value.num)");
System.out.println(node);
List<Map<String, String>> result = Josson.readValueFor(node, List.class);
System.out.println(result);
Output
[{"":"89"},{"1":"19"},{"2":"6"}]
[{=89}, {1=19}, {2=6}]

Read below JSON data and fetch status name

I want to get the name of the status from JSON data.
{
"expand": "renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations",
"id": "3876562",
"self": "https://jira2.abc.com/rest/api/2/issue/3876562",
"key": "DEVACDMY-35289",
"fields": {
"status": {
"self": "https://jira2.abc.com/rest/api/2/status/3",
"description": "",
"iconUrl": "https://jira2.abc.com/images/icons/statuses/inprogress.png",
"name": "In Progress",
"id": "3",
"statusCategory": {
"self": "https://jira2.abc.com/rest/api/2/statuscategory/4",
"id": 4,
"key": "indeterminate",
"colorName": "yellow",
"name": "In Progress"
}
}
}
}
I try this but it doesn't work.
Map address = ((Map)jo.get("fields"));
// iterating address Map
Iterator<Map.Entry> itr1 = address.entrySet().iterator();
while (itr1.hasNext()) {
Map.Entry pair = itr1.next();
Map status=((Map)jo.get(pair.key);
Iterator<Map.Entry> itr2 =status.entrySet().iterator(); while(itr2.hasNext())
{
itr1=((Map)itr2.next()).entrySet().iterator();
while(itr1.hasNext())
{
Map.Entry pair=itr1.next();
System.out.println(pair.getKey()+":"+pair.getValue());
}}
Looking at the json, it is not an array, it is simply a JsonObject and to get the string of the status name you need to traverse the same way.
To get the status name there is a hierarchy that you need to follow
JSONObject --> fields*(this is again a JSONObject)* --> status*(this is
again a JSON object)* -> name (this is string)
Look at the following code
String str = "{\n" +
" \"expand\": \"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations\",\n" +
" \"id\": \"3876562\",\n" +
" \"self\": \"https://jira2.abc.com/rest/api/2/issue/3876562\",\n" +
" \"key\": \"DEVACDMY-35289\",\n" +
" \"fields\": {\n" +
" \"status\": {\n" +
" \"self\": \"https://jira2.abc.com/rest/api/2/status/3\",\n" +
" \"description\": \"\",\n" +
" \"iconUrl\": \"https://jira2.abc.com/images/icons/statuses/inprogress.png\",\n" +
" \"name\": \"In Progress\",\n" +
" \"id\": \"3\",\n" +
" \"statusCategory\": {\n" +
" \"self\": \"https://jira2.abc.com/rest/api/2/statuscategory/4\",\n" +
" \"id\": 4,\n" +
" \"key\": \"indeterminate\",\n" +
" \"colorName\": \"yellow\",\n" +
" \"name\": \"In Progress\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
JSONObject jsonarray = new JSONObject(str);
JSONObject fields = jsonarray.getJSONObject("fields");
JSONObject status = fields.getJSONObject("status");
String name = status.getString("name");
System.out.println("fields : " + fields);
System.out.println("status : " + status);
System.out.println("name: " + name);
output :-
fields : {"status":{"name":"In Progress","self":"https://jira2.abc.com/rest/api/2/status/3","description":"","iconUrl":"https://jira2.abc.com/images/icons/statuses/inprogress.png","id":"3","statusCategory":{"colorName":"yellow","name":"In Progress","self":"https://jira2.abc.com/rest/api/2/statuscategory/4","id":4,"key":"indeterminate"}}}
status : {"name":"In Progress","self":"https://jira2.abc.com/rest/api/2/status/3","description":"","iconUrl":"https://jira2.abc.com/images/icons/statuses/inprogress.png","id":"3","statusCategory":{"colorName":"yellow","name":"In Progress","self":"https://jira2.abc.com/rest/api/2/statuscategory/4","id":4,"key":"indeterminate"}}
name: In Progress

how can I create an arraylist of all possible combinations from a json file

I'm currently creating a Cluedo game and I'm editing the playerpiece class, I have also created a json file called data.json to store data about the playerpiece, for instance: Character (e.g Colonel Mustard), Weapon etc.
{
"PlayerPieces": {
"0": "Col Mustard",
"1": "Prof Plum",
"2": "Rev Green",
"3": "Mrs Peacock",
"4": "Miss Scarlett",
"5": "Mrs White"
},
"Weapons": {
"0": "Dagger",
"1": "Candlestick" ,
"2": "Revolver",
"3": "Rope",
"4": "Lead Piping",
"5": "Spanner"
}
}
At the moment, I'm trying to figure out how I can create an arraylist of all possible instances of the PlayerPieces, any help on how to get started would be greatly, greatly appreciated!
Something like this will help I hope.
String stringToParse = "{\r\n"
+ " \"PlayerPieces\": {\r\n"
+ " \"0\": \"Col Mustard\",\r\n"
+ " \"1\": \"Prof Plum\",\r\n"
+ " \"2\": \"Rev Green\",\r\n"
+ " \"3\": \"Mrs Peacock\",\r\n"
+ " \"4\": \"Miss Scarlett\",\r\n"
+ " \"5\": \"Mrs White\"\r\n"
+ " },\r\n"
+ " \"Weapons\": {\r\n"
+ " \"0\": \"Dagger\",\r\n"
+ " \"1\": \"Candlestick\" ,\r\n"
+ " \"2\": \"Revolver\",\r\n"
+ " \"3\": \"Rope\",\r\n"
+ " \"4\": \"Lead Piping\",\r\n"
+ " \"5\": \"Spanner\"\r\n"
+ " }\r\n"
+ "}";
try {
Map<String, String> attributes = new HashMap<>();
JSONObject obj = new JSONObject(stringToParse);
if (obj.has("PlayerPieces")) {
JSONObject objPlayerPieces = obj.getJSONObject("PlayerPieces");
Iterator<String> keysCat = objPlayerPieces.keys();
while (keysCat.hasNext()) {
String key = keysCat.next();
attributes.put(key, objPlayerPieces.getString(key));
}
}
} catch (JSONException e) {
e.printStackTrace();
}
Therefore, you will get all the attributes of "PlayerPieces" inside the attributes hashmap for as long as you have them defined in the json file.

2 Different Json Objects are printed as a response, how to separate them and read the value of an element in the second Object

I am getting multiple json objects in a http response.
Eg:
{
"result": {
"Status": "complete",
"id1": "<id1>",
"id2": "<id2>",
"Fields": [{
"fid": "1",
"FName": "<name>"
}, {
"fid": "2",
"FName": "<name>"
}, {
"fid": "3",
"FName": "<name>"
}, {
"fid": "4",
"FName": "<name>"
}]
}
}
The next object is
{
"result": {
"Status": "complete",
"id1": "<id1>",
"id2": "<id2>",
"Fields": [{
"fid": "1",
"FName": "<name>"
}, {
"fid": "2",
"FName": "<name>"
}, {
"fid": "3",
"FName": "<name>"
}, {
"fid": "4",
"FName": "<name>"
}],
"TokenPairs": [{
"Token1": "<token1>",
"Token2": "<token2>",
"FieldMatches": {
"additionalProp1": {
"Score": 0,
"FalseDiscoveryRate": 0
},
"additionalProp2": {
"Score": 0,
"FalseDiscoveryRate": 0
},
"additionalProp3": {
"Score": 0,
"FalseDiscoveryRate": 0
}
}
}]
}
}
I actually want to check the TokenPairs but when I check the jsonPath it picks up the 1st object and returns null. How can I skip the 1st object and go to the second object? I m trying to solve it with adding the response (String) to JsonObject but am getting some errors.
I think I found a solution for you. I would like to provide you the following function which will give you two separate JSON String.
public void JSONSeparator(String JsonString) {
try {
JSONObject object1 = (JSONObject) new JSONTokener(jsonString.replaceAll("\\s+", "")).nextValue();
String firstJson = object1.toString().trim();
String nextJson = jsonString.replaceAll("\\s+", "").substring(firstJson.length());
System.out.println("First JSON String: " + firstJson);
System.out.println("Second JSON String: " + nextJson);
} catch (Exception e) {
e.printStackTrace();
}
}
The idea is to take the first JSON token, and then get the remaining part of the string after you get the first. I used the JSONTokener for picking up the first JSONObject. Then took the length of the object and hence I got the second JSON String using substring method.
The JsonString that I used to pass through this function was the following.
private String jsonString = "{\n" +
" \"result\": {\n" +
" \"Status\": \"complete\",\n" +
" \"id1\": \"<id1>\",\n" +
" \"id2\": \"<id2>\",\n" +
" \"Fields\": [{\n" +
" \"fid\": \"1\",\n" +
" \"FName\": \"<name>\"\n" +
" }, {\n" +
" \"fid\": \"2\",\n" +
" \"FName\": \"<name>\"\n" +
" }, {\n" +
" \"fid\": \"3\",\n" +
" \"FName\": \"<name>\"\n" +
" }, {\n" +
" \"fid\": \"4\",\n" +
" \"FName\": \"<name>\"\n" +
" }]\n" +
" }\n" +
"}" + "{" +
" \"result\": {\n" +
" \"Status\": \"complete\",\n" +
" \"id1\": \"<id1>\",\n" +
" \"id2\": \"<id2>\",\n" +
" \"Fields\": [{\n" +
" \"fid\": \"1\",\n" +
" \"FName\": \"<name>\"\n" +
" }, {\n" +
" \"fid\": \"2\",\n" +
" \"FName\": \"<name>\"\n" +
" }, {\n" +
" \"fid\": \"3\",\n" +
" \"FName\": \"<name>\"\n" +
" }, {\n" +
" \"fid\": \"4\",\n" +
" \"FName\": \"<name>\"\n" +
" }],\n" +
" \"TokenPairs\": [{\n" +
" \"Token1\": \"<token1>\",\n" +
" \"Token2\": \"<token2>\",\n" +
" \"FieldMatches\": {\n" +
" \"additionalProp1\": {\n" +
" \"Score\": 0,\n" +
" \"FalseDiscoveryRate\": 0\n" +
" },\n" +
" \"additionalProp2\": {\n" +
" \"Score\": 0,\n" +
" \"FalseDiscoveryRate\": 0\n" +
" },\n" +
" \"additionalProp3\": {\n" +
" \"Score\": 0,\n" +
" \"FalseDiscoveryRate\": 0\n" +
" }\n" +
" }\n" +
" }]\n" +
" }\n" +
"}";
Please note that, in order to get precise index for the substring, we need to remove all spaces and new lines using the replaceAll function that I had used. Hope that little trick helps you.

Json object, convert json array into a json object in java

I have one json array like this
"values":[
{
"locale":"en_US",
"source_key":"book_format",
"value":"Hardback",
"display_attr_name":"Book Format",
"source_value":"Hardback",
"isPrimary":"true"
},
{
"isFacetValue":"true",
"facet_version":"1.1",
"locale":"en_US",
"value":"Hardcover"
}
]
I need to get the only the distinct keys from above json array
{
"locale":"en_US",
"source_key":"book_format",
"value":"Hardback",
"display_attr_name":"Book Format",
"source_value":"Hardback",
"isPrimary":"true",
"isFacetValue":"true",
"facet_version":"1.1"
}
And the output will be in the form of jsonobject.
https://github.com/octomix/josson
Josson josson = Josson.fromJsonString(
"{" +
" \"values\": [" +
" {" +
" \"locale\": \"en_US\"," +
" \"source_key\": \"book_format\"," +
" \"value\": \"Hardback\"," +
" \"display_attr_name\": \"Book Format\"," +
" \"source_value\": \"Hardback\"," +
" \"isPrimary\": \"true\"" +
" }," +
" {" +
" \"isFacetValue\": \"true\"," +
" \"facet_version\": \"1.1\"," +
" \"locale\": \"en_US\"," +
" \"value\": \"Hardcover\"" +
" }" +
" ]" +
"}");
JsonNode node = josson.getNode("values.mergeObjects()");
System.out.println(node.toPrettyString());
Output
{
"locale" : "en_US",
"source_key" : "book_format",
"value" : "Hardcover",
"display_attr_name" : "Book Format",
"source_value" : "Hardback",
"isPrimary" : "true",
"isFacetValue" : "true",
"facet_version" : "1.1"
}

Categories

Resources