I have written a code which parses the JSON body in map it works fine but when JSONArray is detected it throws exception after some iterations.
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class JsonToMapConv {
private static HashMap<String, Object> mapReturn = new HashMap<String, Object>();
public static JsonParser parser = new JsonParser();
public static void main(String[] args) throws Exception{
String json ="{\"menu\": {\n" +
" \"header\": \"SVG Viewer\",\n" +
" \"items\": [\n" +
" {\"id\": \"Open\"},\n" +
" {\"id\": \"OpenNew\", \"label\": \"Open New\"},\n" +
" \n" +
" {\"id\": \"ZoomIn\", \"label\": \"Zoom In\"},\n" +
" {\"id\": \"ZoomOut\", \"label\": \"Zoom Out\"},\n" +
" {\"id\": \"OriginalView\", \"label\": \"Original View\"},\n" +
" \n" +
" {\"id\": \"Quality\"},\n" +
" {\"id\": \"Pause\"},\n" +
" {\"id\": \"Mute\"},\n" +
" \n" +
" {\"id\": \"Find\", \"label\": \"Find...\"},\n" +
" {\"id\": \"FindAgain\", \"label\": \"Find Again\"},\n" +
" {\"id\": \"Copy\"},\n" +
" {\"id\": \"CopyAgain\", \"label\": \"Copy Again\"},\n" +
" {\"id\": \"CopySVG\", \"label\": \"Copy SVG\"},\n" +
" {\"id\": \"ViewSVG\", \"label\": \"View SVG\"},\n" +
" {\"id\": \"ViewSource\", \"label\": \"View Source\"},\n" +
" {\"id\": \"SaveAs\", \"label\": \"Save As\"},\n" +
" \n" +
" {\"id\": \"Help\"},\n" +
" {\"id\": \"About\", \"label\": \"About Adobe CVG Viewer...\"}\n" +
" ]\n" +
"}}";
HashMap<String, Object> map = createHashMapFromJsonString(json,"");
for (Map.Entry<String, Object> entry : map.entrySet()) {
if(!entry.getValue().toString().contains("{"))
System.out.println(entry.getKey()+" : "+entry.getValue());
}
}
public static HashMap<String, Object> createHashMapFromJsonString(String json,String prefix) {
System.out.println("prefix " + prefix);
if(json.startsWith("[",0)){
json = json.replace("[", "");
json = json.replace("]", "");
String subString = json.substring(2,7);
String[] parts = json.split("(?=\\{\""+subString+")");
for(int i=0; i< parts.length; i++ ){
if(null != parts[i] && parts[i].length()>0){
if(parts[i].charAt(parts[i].length() - 1)==','){
System.out.println("parts[for]-"+ i+" is "+parts[i] + "with prefix " + prefix );
parts[i] = parts[i].substring(0,parts[i].length() - 1);
}
createHashMapFromJsonString(parts[i], prefix+"_"+i);
}
}
}
else{
JsonObject object = (JsonObject) parser.parse(json);
Set<Map.Entry<String, JsonElement>> set = object.entrySet();
Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator();
while (iterator.hasNext()) {
Map.Entry<String, JsonElement> entry = iterator.next();
String key = entry.getKey();
if(prefix.length()!=0){
key = prefix + "."+key;
}
JsonElement value = entry.getValue();
if (null != value) {
if (!value.isJsonPrimitive()) {
if (value.isJsonObject()) {
mapReturn.put(key, createHashMapFromJsonString(value.toString(),key));
} else if (value.isJsonArray() && value.toString().contains(":")) {
List<HashMap<String, Object>> list = new ArrayList<>();
JsonArray array = value.getAsJsonArray();
if (null != array) {
for (JsonElement element : array) {
list.add(createHashMapFromJsonString(value.toString(),key));
}
mapReturn.put(key, list);
}
} else if (value.isJsonArray() && !value.toString().contains(":")) {
mapReturn.put(key, value.getAsJsonArray());
}
} else {
mapReturn.put(key, value.getAsString());
}
}
}
}
return mapReturn;
}
}
The Exception i am experincing is :
Exception in thread "main" java.lang.StackOverflowError
at java.util.AbstractMap.toString(AbstractMap.java:547)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
The sample json, i have used is from https://json.org/example.html website .
In order to test the code just reassign the json string with required value.
The error is thrown on entry.getValue().toString() for one of the map entries, since this entry's value contains the original map.
To see which entry it is, simple debug your application, and look at the value of map after calling createHashMapFromJsonString(json,"").
That said, I strongly suggest that you use an existing JSON parsing framework, as advised in the comments to your question.
There is no point in "inventing the wheel".
A library which is widely used, for a long period of time, by many users, is much less likely to have bugs than any newly written code.
Related
I want to convert JSON response to Map what is the best approach to get the desired output using GSON library.
I try this and I'm getting only the ArrayList value.
Map<String, Object> map = gson.fromJson(response, HashMap.class);
ArrayList responseOptions = (ArrayList) map.get("data");
output:
[{language=Java, value=8}, {language=Ruby, value=7}, {language=Python, value=7}]
Sample JSON Response
{
"data":[
{
"language":"Java","value":"8"
},
{
"language":"Ruby","value":"7"
},
{
"language":"Python","value":"6"
}]
}
Desired Output in Map
{Java=8, Ruby=7, Python=6}
Test code
String str = "{\n" +
" \"data\":[\n" +
" {\n" +
" \"language\":\"Java\",\"value\":\"8\"\n" +
" },\n" +
" {\n" +
" \"language\":\"Ruby\",\"value\":\"7\"\n" +
" },\n" +
" {\n" +
" \"language\":\"Python\",\"value\":\"6\"\n" +
" }]\n" +
"}";
Map map = new Gson().fromJson(str, Map.class);
List data = (List) map.get("data");
Map<String, String> result = new HashMap<>();
for (Object o : data) {
Map m = (Map) o;
result.put(m.get("language").toString(), m.get("value").toString());
}
System.out.println(result);
Test result
Hi I need to read all key, values from nested JSON, where ever there is inner JSON. I need that values ignoring the key.From below JSON i need Key values for nested JSON, like: responseStatus-passed, "statusCode":"200", "retrieveQuoteResponse":null,"quoteGuid":null, etc.ignoring the start key value like: responsePreamble, quoteProductList which has a nested json inside it.
{
"responsePreamble": {
"responseStatus": "Passed",
"statusCode": "200",
"responseMessage": "Records Found"
},
"retrieveQuoteResponse": null,
"totalQuoteProductCount": 2,
"quoteProductList": {
"quoteGuid": null,
"quantity": 180
}
Code:
ObjectReader reader = new ObjectMapper().readerFor(Map.class);
Map<String, Map<String, String>> employeeMap = reader.readValue(jsonObject);
for (Entry<String, Map<String, String>> empMap : employeeMap.entrySet()) {
Map<String, String> addMap = empMap.getValue();
if(addMap!=null) {
for (Entry<String, String> addressSet : addMap.entrySet()) {
System.out.println(addressSet.getKey() + " :: " + addressSet.getValue());
}
}
}
OutPut:
responseStatus :: Passed
statusCode :: 200
responseMessage :: Records Found
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map
at com.im.api.tests.CompareTwoJsons.main(CompareTwoJsons.java:78)
For your specific case, the following code will do the job:
String json = "{\n" +
" \"responsePreamble\":{\n" +
" \"responseStatus\":\"Passed\",\n" +
" \"statusCode\":\"200\",\n" +
" \"responseMessage\":\"Records Found\",\n" +
" \"accountInfo\":{\n" +
" \"id\":\"631b3d5b-62c8-e711-80f3-3863bb343ba0\"\n" +
" },\n" +
" \"account\":\"40114570\",\n" +
" \"contactInfo\":{\n" +
" \"id\":\"1af63ebb-2680-eb11-a812-000d3a4e381d\"\n" +
" },\n" +
" \"contact\":\"Kenny Tokuda\",\n" +
" \"currencyInfo\":{\n" +
" \"id\":\"8c2ef-\",\n" +
" \"symbol\":\"$\"\n" +
" },\n" +
" \"vendorCurrencyInfo\":{\n" +
" \"id\":null\n" +
" }\n" +
" },\n" +
" \"retrieveQuoteResponse\":null,\n" +
" \"totalQuoteProductCount\":2,\n" +
" \"quoteProductList\":{\n" +
" \"quoteGuid\":null,\n" +
" \"quantity\":180\n" +
" }\n" +
"}";
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(json);
Iterator<String> iterator = jsonNode.fieldNames();
while (iterator.hasNext()) {
String key = iterator.next();
printRec(jsonNode, key);
}
Here is how function printRec looks like:
public static void printRec(JsonNode jsonNode, String key) {
JsonNode node = jsonNode.get(key);
if (node.isObject()) {
Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
fields.forEachRemaining(field -> {
printRec(node, field.getKey());
if (!field.getValue().isObject()) {
System.out.println(field.getKey() + " : " + field.getValue());
}
});
}
}
When you run this code you should see the following output:
responseStatus : "Passed"
statusCode : "200"
responseMessage : "Records Found"
id : "631b3d5b-62c8-e711-80f3-3863bb343ba0"
account : "40114570"
id : "1af63ebb-2680-eb11-a812-000d3a4e381d"
contact : "Kenny Tokuda"
id : "8c2ef-"
symbol : "$"
id : null
quoteGuid : null
quantity : 180
I want to extract jkl object from below JSON string. Also after extraction, I want the backslashes to be removed and extract further with the braces. I followed few questions on StackOverflow but it didn't help much.
{
"abc:def": {
"ghi": {
"jkl": "{\"mno:pqr\":{\"ty\":4,\"\\nsensing_service_name:\\\"Number\\\",\\nsensing_service_id: 20\\n}\\n ]\\n}\"}}",
"st": {
"op": 5,
"org": "q9wr9qrq"
},
"uvw": 1
},
"xyz": false
}
}
I tried below code to display jkl object but it is not working. Please suggest what is wrong in this and how to correct the same
JSONObject json = (JSONObject) JSONSerializer.toJSON(data);
JSONObject aa = json.getJSONObject("abc:def");
JSONObject bb = aa.getJSONObject("ghi");
JSONObject cc = bb.getJSONObject("jkl");
System.out.println(cc);
Hope this will help you:
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
public class TestClass {
public static void main(String[] args) throws Exception {
String jsonString = "{\n" +
" \"abc:def\": {\n" +
" \"ghi\": {\n" +
" \"jkl\": \"{\\\"mno:pqr\\\":{\\\"ty\\\":4,\\\"\\\\nsensing_service_name:\\\\\\\"Number\\\\\\\",\\\\nsensing_service_id: 20\\\\n}\\\\n ]\\\\n}\\\"}}\",\n" +
" \"st\": {\n" +
" \"op\": 5,\n" +
" \"org\": \"q9wr9qrq\"\n" +
" },\n" +
" \"uvw\": 1\n" +
" },\n" +
" \"xyz\": false\n" +
" }\n" +
"} ";
JSONObject jsonObject = new JSONObject(jsonString);
jsonObject = (JSONObject) jsonObject.get("abc:def");
jsonObject = (JSONObject) jsonObject.get("ghi");
String result = jsonObject.getString("jkl");
result = StringUtils.replace(result, "\\n", "");
System.out.println(result.replaceAll("\\\\",""));
}
}
I want to retrieve all the values based on a key value from JSON object.
here's my sample JSON:
[{
"zip":544,
"type":"UNIQUE",
"primary_city":"Holtsville",
"acceptable_cities":"",
"unacceptable_cities":"Irs Service Center",
"state":"NY",
"county":"Suffolk County",
"timezone":"America/New_York",
"area_codes":"631",
"latitude":40.81,
"longitude":-73.04,
"world_region":"NA",
"country":"US",
"decommissioned":0,
"estimated_population":0,
"notes":""
},
{
"zip":601,
"type":"STANDARD",
"primary_city":"Adjuntas",
"acceptable_cities":"",
"unacceptable_cities":"Colinas Del Gigante, Jard De Adjuntas, Urb San Joaquin",
"state":"PR",
"county":"Adjuntas",
"timezone":"America/Puerto_Rico",
"area_codes":"787,939",
"latitude":18.16,
"longitude":-66.72,
"world_region":"NA",
"country":"US",
"decommissioned":0,
"estimated_population":0,
"notes":""
}]
So based on my zip code as key, I want to retrieve all other values.
I had tried the same thing for a JSON object with single key-value pairs, but don't know how to do it for above JSON object.
Here's my successfully running code for single key-value pairs
import java.util.HashMap;
import java.util.Iterator;
import org.json.JSONObject;
public class map {
public static void main(String[] args) {
String t = "{\"A\":\"A1\",\"B\":\"B1\",\"C\":\"C1\"}";
HashMap<String, String> map = new HashMap<String, String>();
JSONObject jObject = new JSONObject(t);
Iterator<?> keys = jObject.keys();
while( keys.hasNext() ){
String key = (String)keys.next();
String value = jObject.getString(key);
map.put(key, value);
}
System.out.println("json : "+jObject);
System.out.println("map : "+map.get("A"));
}
}
Output:
json : {"A":"A1","B":"B1","C":"C1"}
map : A1
any suggestions of how to do it?
I had seen several previous answers but none of them addresses this issue?
you can do it something like this. at the end of the loop your map will have zip to JSONObject mapping.
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
String json = "[{\n" +
" \"zip\":544,\n" +
" \"type\":\"UNIQUE\",\n" +
" \"primary_city\":\"Holtsville\",\n" +
" \"acceptable_cities\":\"\",\n" +
" \"unacceptable_cities\":\"Irs Service Center\",\n" +
" \"state\":\"NY\",\n" +
" \"county\":\"Suffolk County\",\n" +
" \"timezone\":\"America/New_York\",\n" +
" \"area_codes\":\"631\",\n" +
" \"latitude\":40.81,\n" +
" \"longitude\":-73.04,\n" +
" \"world_region\":\"NA\",\n" +
" \"country\":\"US\",\n" +
" \"decommissioned\":0,\n" +
" \"estimated_population\":0,\n" +
" \"notes\":\"\"\n" +
" },\n" +
" {\n" +
" \"zip\":601,\n" +
" \"type\":\"STANDARD\",\n" +
" \"primary_city\":\"Adjuntas\",\n" +
" \"acceptable_cities\":\"\",\n" +
" \"unacceptable_cities\":\"Colinas Del Gigante, Jard De Adjuntas, Urb San Joaquin\",\n" +
" \"state\":\"PR\",\n" +
" \"county\":\"Adjuntas\",\n" +
" \"timezone\":\"America/Puerto_Rico\",\n" +
" \"area_codes\":\"787,939\",\n" +
" \"latitude\":18.16,\n" +
" \"longitude\":-66.72,\n" +
" \"world_region\":\"NA\",\n" +
" \"country\":\"US\",\n" +
" \"decommissioned\":0,\n" +
" \"estimated_population\":0,\n" +
" \"notes\":\"\"\n" +
" }]";
Map<Integer, JSONObject> map = new HashMap<>();
JSONArray array = new JSONArray(json);
for (int i = 0; i < array.length(); i++) {
JSONObject jsonObject = array.getJSONObject(i);
map.put(jsonObject.getInt("zip"), jsonObject);
}
}
}
I am trying to parse a JSON string in java to have the individual value printed separately. But while making the program run I get the following error-
Exception in thread "main" java.lang.RuntimeException: Stub!
at org.json.JSONObject.<init>(JSONObject.java:7)
at ShowActivity.main(ShowActivity.java:29)
My Class looks like-
import org.json.JSONException;
import org.json.JSONObject;
public class ShowActivity {
private final static String jString = "{"
+ " \"geodata\": ["
+ " {"
+ " \"id\": \"1\","
+ " \"name\": \"Julie Sherman\","
+ " \"gender\" : \"female\","
+ " \"latitude\" : \"37.33774833333334\","
+ " \"longitude\" : \"-121.88670166666667\""
+ " }"
+ " },"
+ " {"
+ " \"id\": \"2\","
+ " \"name\": \"Johnny Depp\","
+ " \"gender\" : \"male\","
+ " \"latitude\" : \"37.336453\","
+ " \"longitude\" : \"-121.884985\""
+ " }"
+ " }"
+ " ]"
+ "}";
private static JSONObject jObject = null;
public static void main(String[] args) throws JSONException {
jObject = new JSONObject(jString);
JSONObject geoObject = jObject.getJSONObject("geodata");
String geoId = geoObject.getString("id");
System.out.println(geoId);
String name = geoObject.getString("name");
System.out.println(name);
String gender=geoObject.getString("gender");
System.out.println(gender);
String lat=geoObject.getString("latitude");
System.out.println(lat);
String longit =geoObject.getString("longitude");
System.out.println(longit);
}
}
Let me know what is it I am missing, or the reason why I do get that error everytime I run the application. Any comments would be appreciated.
See my comment.
You need to include the full org.json library when running as android.jar only contains stubs to compile against.
In addition, you must remove the two instances of extra } in your JSON data following longitude.
private final static String JSON_DATA =
"{"
+ " \"geodata\": ["
+ " {"
+ " \"id\": \"1\","
+ " \"name\": \"Julie Sherman\","
+ " \"gender\" : \"female\","
+ " \"latitude\" : \"37.33774833333334\","
+ " \"longitude\" : \"-121.88670166666667\""
+ " },"
+ " {"
+ " \"id\": \"2\","
+ " \"name\": \"Johnny Depp\","
+ " \"gender\" : \"male\","
+ " \"latitude\" : \"37.336453\","
+ " \"longitude\" : \"-121.884985\""
+ " }"
+ " ]"
+ "}";
Apart from that, geodata is in fact not a JSONObject but a JSONArray.
Here is the fully working and tested corrected code:
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class ShowActivity {
private final static String JSON_DATA =
"{"
+ " \"geodata\": ["
+ " {"
+ " \"id\": \"1\","
+ " \"name\": \"Julie Sherman\","
+ " \"gender\" : \"female\","
+ " \"latitude\" : \"37.33774833333334\","
+ " \"longitude\" : \"-121.88670166666667\""
+ " },"
+ " {"
+ " \"id\": \"2\","
+ " \"name\": \"Johnny Depp\","
+ " \"gender\" : \"male\","
+ " \"latitude\" : \"37.336453\","
+ " \"longitude\" : \"-121.884985\""
+ " }"
+ " ]"
+ "}";
public static void main(final String[] argv) throws JSONException {
final JSONObject obj = new JSONObject(JSON_DATA);
final JSONArray geodata = obj.getJSONArray("geodata");
final int n = geodata.length();
for (int i = 0; i < n; ++i) {
final JSONObject person = geodata.getJSONObject(i);
System.out.println(person.getInt("id"));
System.out.println(person.getString("name"));
System.out.println(person.getString("gender"));
System.out.println(person.getDouble("latitude"));
System.out.println(person.getDouble("longitude"));
}
}
}
Here's the output:
C:\dev\scrap>java -cp json.jar;. ShowActivity
1
Julie Sherman
female
37.33774833333334
-121.88670166666667
2
Johnny Depp
male
37.336453
-121.884985
To convert your JSON string to hashmap you can make use of this :
HashMap<String, Object> hashMap = new HashMap<>(Utility.jsonToMap(response)) ;
Use this class :) (handles even lists , nested lists and json)
public class Utility {
public static Map<String, Object> jsonToMap(Object json) throws JSONException {
if(json instanceof JSONObject)
return _jsonToMap_((JSONObject)json) ;
else if (json instanceof String)
{
JSONObject jsonObject = new JSONObject((String)json) ;
return _jsonToMap_(jsonObject) ;
}
return null ;
}
private static Map<String, Object> _jsonToMap_(JSONObject json) throws JSONException {
Map<String, Object> retMap = new HashMap<String, Object>();
if(json != JSONObject.NULL) {
retMap = toMap(json);
}
return retMap;
}
private static Map<String, Object> toMap(JSONObject object) throws JSONException {
Map<String, Object> map = new HashMap<String, Object>();
Iterator<String> keysItr = object.keys();
while(keysItr.hasNext()) {
String key = keysItr.next();
Object value = object.get(key);
if(value instanceof JSONArray) {
value = toList((JSONArray) value);
}
else if(value instanceof JSONObject) {
value = toMap((JSONObject) value);
}
map.put(key, value);
}
return map;
}
public static List<Object> toList(JSONArray array) throws JSONException {
List<Object> list = new ArrayList<Object>();
for(int i = 0; i < array.length(); i++) {
Object value = array.get(i);
if(value instanceof JSONArray) {
value = toList((JSONArray) value);
}
else if(value instanceof JSONObject) {
value = toMap((JSONObject) value);
}
list.add(value);
}
return list;
}
}
credit to this blog
This answer may help someone whose requirements are different.
This is your Json string
{
"pageNumber":20,
"pageTitle":"example page title",
"pageInfo": {
"pageName": "Homepage",
"logo": "https://www.example.com/logo.jpg"
},
"posts": [
{
"post_id": "0123456789",
"actor_id": "1001",
"author_name": "Jane Doe",
"post_title": "How to parse JSON in Java",
"comments": [],
"time_of_post": "1234567890"
}
]
}
and this is how to read it
import org.json.JSONArray;
import org.json.JSONObject;
public class ParseJSON {
static String json = "...";
public static void main(String[] args) {
JSONObject obj = new JSONObject(json);
String pageTitle = obj.getString("pageTitle");
String pageNumber= obj.getInt("pageNumber");
String pageName = obj.getJSONObject("pageInfo").getString("pageName");
System.out.println(pageNumber);
System.out.println(pageTitle );
System.out.println(pageName);
JSONArray arr = obj.getJSONArray("posts");
for (int i = 0; i < arr.length(); i++) {
String post_id = arr.getJSONObject(i).getString("post_id");
System.out.println(post_id);
}
}
}
Looks like for both of your objects (inside the array), you have an extra closing brace after "Longitude".
Firstly there is an extra } after every array object.
Secondly "geodata" is a JSONArray. So instead of JSONObject geoObject = jObject.getJSONObject("geodata"); you have to get it as JSONArray geoObject = jObject.getJSONArray("geodata");
Once you have the JSONArray you can fetch each entry in the JSONArray using geoObject.get(<index>).
I am using org.codehaus.jettison.json.
Here is the example of one Object, For your case you have to use JSONArray.
public static final String JSON_STRING="{\"employee\":{\"name\":\"Sachin\",\"salary\":56000}}";
try{
JSONObject emp=(new JSONObject(JSON_STRING)).getJSONObject("employee");
String empname=emp.getString("name");
int empsalary=emp.getInt("salary");
String str="Employee Name:"+empname+"\n"+"Employee Salary:"+empsalary;
textView1.setText(str);
}catch (Exception e) {e.printStackTrace();}
//Do when JSON has problem.
}
I don't have time but tried to give an idea. If you still can't do it, then I will help.
you have an extra "}" in each object,
you may write the json string like this:
public class ShowActivity {
private final static String jString = "{"
+ " \"geodata\": ["
+ " {"
+ " \"id\": \"1\","
+ " \"name\": \"Julie Sherman\","
+ " \"gender\" : \"female\","
+ " \"latitude\" : \"37.33774833333334\","
+ " \"longitude\" : \"-121.88670166666667\""
+ " }"
+ " },"
+ " {"
+ " \"id\": \"2\","
+ " \"name\": \"Johnny Depp\","
+ " \"gender\" : \"male\","
+ " \"latitude\" : \"37.336453\","
+ " \"longitude\" : \"-121.884985\""
+ " }"
+ " }"
+ " ]"
+ "}";
}