How to generate JSON string in Java using net.sf.json? - java

I am struggling to generate JSON String in Java.
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
JSONArray ja = new JSONArray();
JSONObject js = new JSONObject();
JSONObject j = new JSONObject();
String s = "[{\"shakil\",\"29\",\"7676\"}]";
js.put("id", "1");
js.put("data", s);
ja.add(js);
j.put("rows", ja);
System.out.println(j.toString());
actual output:
{"rows":[{"id":"2","data":"[{\"shakil\",\"29\",\"7676\"}]"}]}
expected output:
{"rows":[{"id":"2","data":["shakil", "29","7676"]}]};

Your s is a String which is not unquoted when put into a JSONObject. You must build another JSONArray for the value of data:
// using http://jettison.codehaus.org/
JSONObject outerObject = new JSONObject();
JSONArray outerArray = new JSONArray();
JSONObject innerObject = new JSONObject();
JSONArray innerArray = new JSONArray();
innerArray.put("shakil");
innerArray.put("29");
innerArray.put("7676");
innerObject.put("id", "2");
innerObject.put("data", innerArray);
outerArray.put(innerObject);
outerObject.put("rows", outerArray);
System.out.println(outerObject.toString());
Result:
{
"rows": [
{
"id": "2",
"data": [
"shakil",
"29",
"7676"
]
}
]
}

Write
String[] s = new String[] {"shakil", "29" , "7676"};
instead of
String s = "[{\"shakil\",\"29\",\"7676\"}]";

Check out gson, it'll provide you with a whole lot of options for serializing/deserializing your Java objects to/from JSON.
Example taken from the page
Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
String[] strings = {"abc", "def", "ghi"};
//(Serialization)
gson.toJson(ints); ==> prints [1,2,3,4,5]
gson.toJson(strings); ==> prints ["abc", "def", "ghi"]
//(Deserialization)
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);

Finally found answer for net.sf.json
JSONArray data1 = new JSONArray();
data1.add("shakil");
data1.add("29");
data1.add("100");
JSONObject inner1 = new JSONObject();
inner1.put("id", "1");
inner1.put("data", data1);
JSONArray list2 = new JSONArray();
list2.add(inner1);
JSONObject finalObj = new JSONObject();
finalObj.put("rows", list2);
System.out.println(finalObj);

Not being able to declare a JSON string in Java is huge pain. Mainly due to (a) no multiline strings (b) escaping double quotes makes it a mess wrt readability.
I work around this by using single quotes to declare the JSON string (using the standard multiline concatenation). Nothing fancy:
String jsonStr =
"{" +
"'address': " +
"{" +
"'name': '" + name + "'," +
"'city': '" + city + "'," +
"'street1': '"+ street1 +"'," +
"'street2': '"+ street2 +"'," +
"'zip': '" + zip + "', " +
"'state':'" + state + "'," +
"'country': '" + country + "'," +
"'phone': '" + phone + "'" +
"}" +
"}";
jsonStr = MyUtil.requote(jsonStr);
System.out.println(jsonStr);
MyUtil
public static String requote(String jsonString) {
return jsonString.replace('\'', '"');
}
Some might find this more cumbersome than declaring a Map but this works for me when I have to build a JSON with just string syntax.

I see a lot of problems when writing a json as String directly without using a Objectmapper or similar.
I would suggest you to write your Json (as you defined it):
{"rows":[{"id":"2","data":["shakil", "29","7676"]}]}
and then simply use this little online tool: http://www.jsonschema2pojo.org/
Which can convert a simply Json a Java-Class also with multiple classes. You can there choose during generation if you want to use Gson or Jackson later.
Gson is a little bit lightweighter and may is better for beginning. I prefer Jackson because you can create something like a computed property - but that's already to much detail.
https://code.google.com/p/google-gson/
After adding Gson all you need to do is:
Gson gson = new Gson();
MyGeneratedClass target = new MyGeneratedClass();
String json = gson.toJson(target);
As voila: you have generated a simple json without thinking about how to change it later!

Related

How to retrieve json array elements from JSON object in Java?

JSONObject firstObject = (JSONObject) jsonParser.parse(new FileReader(firstNamesPath));
I have this JSONObject, and I want to be able to access elements in the array inside of it. The object opens successfully, I just don't know how to access the array called "firstNames". It is in a file, and the object looks like this.
{
"firstNames": [
"Aaron",
"Abigail",
"Albert",
"Bob"
]
}
Edit: I am using org.json.simple.JSONObject . If this is not recommended, I am more than willing to change it.
There are several ways to retrieve the json array value:
Assume we have a jsonString
jsonString = "{\n" + " \"firstNames\": [ \n" + " \"Aaron\",\n" + " \"Abigail\",\n" + " \"Albert\",\n" + " \"Bob\"\n" + " ]\n" + "}";
(since many classes share similar names, I am using the groupId and artifactId for distinction.)
Simple cases: use generic JSONObjects and JSONArrays.
json-simple (which OP is using) json-simple website, maven :
org.json.simple.parser.JSONParser jsonParser = new org.json.simple.parser.JSONParser();
org.json.simple.JSONObject firstObject = (org.json.simple.JSONObject) jsonParser.parse(jsonString);
org.json.simple.JSONArray jsonArray = (org.json.simple.JSONArray) firstObject.get("firstNames");
System.out.println(jsonArray);
JSON in Java (mentioned in adendrata's answer): JSON-Java doc, maven
org.json.JSONObject secondObject = new org.json.JSONObject(jsonString);
org.json.JSONArray jsonArray2 = secondObject.getJSONArray("firstNames");
System.out.println(jsonArray2);
gson: Gson, maven
com.google.gson.JsonObject thirdObject = com.google.gson.JsonParser.parseString(jsonString).getAsJsonObject();
System.out.println(thirdObject.get("firstNames").getAsJsonArray());
For more complicated use cases, if you'd like to define your own class, and want to deserialize JSON string to your class, then you can use Gson or Jackson:
// Create your own class:
/*
public class YourOwnClass {
private List<String> firstNames;
public List<String> getFirstNames() {
return firstNames;
}
}
*/
Gson gson = new Gson();
YourOwnClass customObject1 = gson.fromJson(jsonString, YourOwnClass.class);
System.out.println(customObject1.getFirstNames());
ObjectMapper mapper = new ObjectMapper();
YourOwnClass customObject2 = mapper.readValue(jsonString, YourOwnClass.class);
System.out.println(customObject2.getFirstNames());
you can use JSONArray to get array type of Json and looping to access each index
example:
JSONArray array = firstObject.getJSONArray("firstNames");
for (int i = 0; i < array.length(); i++) {
System.out.println("Hello i'm " + array.get(i));
}
Try to use this : com.alibaba.fastjson.JSONObject, and here's the dependency:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.41</version>
</dependency>
Then you can directly use the getJSONArray method the answer shown above.

parse strange Json response to a list

I want to parse this object to a list of string. I do not need the key but just want the value as a list of string.
I cannot have a simple model classes because the keys object are more than 1000 in some responses and are random.
So please any idea how to parse it to list in kotlin or java?
{
"data": {
"21": "593754434425",
"22": "4560864343802",
"23": "7557134347529",
"24": "5937544344255",
"25": "45608643438024",
"26": "75571343475293"
}
}
You could first deserialize it as it is, and then convert to a list.
The JSON can be represented this way:
data class Response(val data: Map<String, String>)
You can mark this class #Serializable and use Kotlinx Serialization to deserialize it, or you can use other libraries like Moshi or Jackson (with jackson-module-kotlin).
Once it's deserialized, simply get the values of the map (it's a collection):
val response = Json.decodeFromString<Response>(yourJsonString)
// this is a Collection, not List, but it should be good enough
val stringValues = response.data.values
// if you really need a List<String>
val list = stringValues.toList()
If you want to get the values in the natural order of the keys, you can also use something like:
val values = response.data.toSortedMap(compareBy<String> { it.toInt() }).values
You can use this to parse your data:
val it: Iterator<String> = json.keys()
val arrayList = ArrayList<String>()
while (it.hasNext()) {
val key = it.next()
arrayList.add(json.get(key))
}
A better way is to change the json model, if you access it.
{
"data": [
"593754434425","4560864343802",
"7557134347529","5937544344255",
"45608643438024","75571343475293"
]
}
For this problem, its handy to use the libriary org.json.
See following code snippet:
import org.json.JSONObject;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// Defining the input
String input = "{\n" +
" \"data\": {\n" +
" \"21\": \"593754434425\",\n" +
" \"22\": \"4560864343802\",\n" +
" \"23\": \"7557134347529\",\n" +
" \"24\": \"5937544344255\",\n" +
" \"25\": \"45608643438024\",\n" +
" \"26\": \"75571343475293\"\n" +
" }\n" +
"}\n";
// Parsing it to a json object with org.json
JSONObject inputJson = new JSONObject(input);
// If inputJson does not contain the key data, we return
if(!inputJson.has("data")) return;
// Else we read this data object to a new JSONObject
JSONObject dataJson = inputJson.getJSONObject("data");
// Define an array list where all the values will be contained
ArrayList<String> values = new ArrayList<>();
// Get a key set of the dat json object. For each key we get its respective value and add it to our value array list
for (String key : dataJson.keySet()) values.add(dataJson.getString(key));
// Print all values
for (String value : values) System.out.println(value);
}
}
=>
4560864343802
7557134347529
5937544344255
45608643438024
75571343475293
593754434425
Installing org.json is the easiest with a package manager like maven or gradle.
Guys i have comeup with a similar solution for the problem here
this is my model class
data class UnVerifiedTagIds(
#SerializedName("data")
val data: Object
)
and this is how i parse the respone here
val values: ArrayList<String> = ArrayList()
val list_of_tag_ids: ArrayList<String> =response.data as ArrayList<String>
The ist one is the dataclass for the response
and the 2nd one is the ApiCallInterface m using Retrofit...
and the last one is the apicall itself
I am using Kotlin language
do class name with name like this data class Result(val data:Map<String,String>)
and using library GSON for convert string json to this model
val json = "{\n" +
" \"data\": {\n" +
" \"21\": \"593754434425\",\n" +
" \"22\": \"4560864343802\",\n" +
" \"23\": \"7557134347529\",\n" +
" \"24\": \"5937544344255\",\n" +
" \"25\": \"45608643438024\",\n" +
" \"26\": \"75571343475293\"\n" +
" }\n" +
"}"
val dat = Gson().fromJson(json,Result::class.java)
if (dat.data.isNotEmpty()){
val list= dat.data.values.toMutableList()
print(list)
}
that works fine with me

Could not write JSON: Direct self-reference leading to cycle

Getting this error :
nested exception is
com.fasterxml.jackson.databind.JsonMappingException: Direct
self-reference leading to cycle (through reference chain:
com.google.gson.JsonObject["asJsonObject"])
when trying to do this :
restTemplate.postForObject(url_final, convertedObject, Object[].class);
where convertedObject is a JSONObject and urlfinal is a String url.
Payload is:
"data" : [
{"FILENAME":"EEC1.TXT",
"ERRORDESCRIPTION":"FTD-07-INVALID CHARACTER FOUND IN THE FILE.",
"LINENO":3},
{"FILENAME":"SEC1.TXT",
"ERRORDESCRIPTION":"26-FTD-07-INVALID CHARACTER FOUND IN THE FILE.",
"LINENO":447}]
My Code:
JSONObject output = new JSONObject(payload);
JSONArray jsonArray = output.getJSONArray("data");
JSONObject objects = jsonArray.getJSONObject(0);
String fileName = objects.getString("FILENAME");
int lineNumber = objects.getInt("LINENO");
String errordesc = objects.getString("ERRORDESCRIPTION");
String tempor = "{\"activityType\": \"trial.start\",\"aFileName\":\""
+ fileName
+ "\",\"aLINENO\": \""
+ lineNumber
+ "\",\"aREFNO\": \""
+ TxnNo
+ "\", \"aERRORDESCRIPTION\": \""+errordesc+"\"}";
JsonObject convertedObject = new Gson().fromJson(tempor, JsonObject.class);
restTemplate.postForObject(url_final, convertedObject, Object[].class);
In ten lines you mixed up 3 different JSON libraries:
JSONObject comes from org.json.
Gson comes from Google's gson.
restTemplate uses behind the scene Jackson.
You should skip first two and use only Jackson. Above code after changes could look like:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
....
ObjectMapper mapper = JsonMapper.builder().build();
JsonNode output = mapper.readTree(payload);
ArrayNode jsonArray = (ArrayNode)output.get("data");
JsonNode objects = jsonArray.get(0);
String fileName = objects.get("FILENAME").asText();
int lineNumber = objects.get("LINENO").asInt();
String errordesc = objects.get("ERRORDESCRIPTION").asText();
String tempor = "{\"activityType\": \"trial.start\",\"aFileName\":\""
+ fileName
+ "\",\"aLINENO\": \""
+ lineNumber
+ "\",\"aREFNO\": \""
+ TxnNo
+ "\", \"aERRORDESCRIPTION\": \""+errordesc+"\"}";
JsonNode convertedObject = mapper.readTree(tempor);
Since version 2.10.0 you can use JsonMapper.builder().build() but in previous versions you can just create new instance by new ObjectMapper() which is also fine.

Java get value by key in JSON data [duplicate]

This question already has answers here:
How to parse JSON in Java
(36 answers)
Closed 3 years ago.
[
{
"boylam":31.8039,
"enlem":40.5906,
"il":"",
"ilPlaka":"",
"ilce":"",
"oncelik":0,
"yukseklik":2052,
"aciklama":"",
"modelId":124774,
"gps":0
}]
Hi I have such a JSON data in my hand. I had a hard time getting the data out of here. For example, how do I print the "boylam" option in JSON data?
You can use JSON.simple to convert string data to JSON objects. https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple/1.1.1
public static void main(String[] args) throws ParseException {
String data = "[\n" +
"{\n" +
" \"boylam\":31.8039,\n" +
" \"enlem\":40.5906,\n" +
" \"il\":\"\",\n" +
" \"ilPlaka\":\"\",\n" +
" \"ilce\":\"\",\n" +
" \"oncelik\":0,\n" +
" \"yukseklik\":2052,\n" +
" \"aciklama\":\"\",\n" +
" \"modelId\":124774,\n" +
" \"gps\":0\n" +
"}]";
JSONParser parser = new JSONParser();
JSONArray jsonArray = (JSONArray) parser.parse(data);
JSONObject jsonObject = (JSONObject) jsonArray.get(0);
System.out.println(jsonObject.get("boylam"));
}
Use Google Gson,the code maybe like this:
// construct the json object
JsonArray jsonArray = new JsonArray();
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("boylam",31.8039);
jsonArray.add(jsonObject);
// iterate the json array
jsonArray.forEach(jsonElement -> {
JsonObject element = (JsonObject) jsonElement;
System.out.println(element.get("boylam"));
});
using com.google.gson.Gson class, you can do this.
Gson gson= new Gson();
JSONObject json=new JSONObject();
json.put("boylam", "31.8039"); // this is your json object
Map map=gson.fromJson(json.toString(), Map.class);
System.out.println(map.get("boylam")); //ouput 31.8039

reading data from nested JSON Object using java

i am struggling with reading some values from JSON object which i get it when i hit REST API..
MY GOAL: i need to iterate over each set of data inside data object array check the value of TRAN_ID and take action accordingly.
below is the format of data
{
"data": [
{
"CUST_ID": "CUST7",
"EXPRY_DATE": null,
"PARAMS": "[{TRAN_IND:savings},{TRAN_TYP:Debit},{country:US}]"
},
{
"CUST_ID": "CUST8",
"EXPRY_DATE": null,
"PARAMS": "[{TRAN_IND:current},{TRAN_TYP:Debit},{country:US}]"
}
]
}
it looks easy and i have tried multiple solutions out there on internet but i dont know it doesnt work for me and i get below error while reading "PARAMS" and converting it to JSONArray for further processing
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to org.json.simple.JSONArray
What i have tried:
private static void jsonParser(String jsonStr) throws ParseException {
JSONObject data= (JSONObject)JSONValue.parse(jsonStr );
JSONArray jsonObj = (JSONArray)data.get("data");
JSONObject JsonRow = (JSONObject)jsonObj.get(0);
JSONArray servParam= (JSONArray) JsonRow.get("PARAMS");
String tran_ind=(String) servParam.get(0);
System.out.println( tran_ind);
}
I'm guessing this is what you what?
try{
JSONObject obj = new JSONObject(sample);
JSONArray data = obj.getJSONArray("data");
for(int i=0; i<data.length(); i++){
JSONObject detail = data.getJSONObject(i);
detail.getString("CUST_ID"); //here is the customer id
detail.getString("EXPRY_DATE"); //here is the exp date
JSONArray params = detail.getJSONArray("PARAMS");
for(int j=0; j<params.length(); j++){
// {TRAN_IND:current},{TRAN_TYP:Debit},{country:US}
JSONObject res = params.getJSONObject(j);
String tran_ind = res.toString();
String tran_type = res.toString();
String country = res.toString();
out.println(tran_ind + " " +tran_type + " " + country);
}
}
}catch (JSONException ex){
ex.printStackTrace();
}
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to org.json.simple.JSONArray
=> Because you are trying to parse String value "[{TRAN_IND:savings},{TRAN_TYP:Debit},{country:US}]" into the JsonArray by code:
JSONArray servParam= (JSONArray) JsonRow.get("PARAMS");
Params seems to be a String, actually.
Don't write your own parser. If you only need to read that string in each element of the array, I would simply cast the whole JSON to a Map with Jackson:
HashMap<String,Object> parsed =
new ObjectMapper().readValue(JSON_SOURCE, HashMap.class);
and then iterate over the "data" element (which would be a list of maps).
List<Map> data = (List) parsed.get("data");
The real problem is that those are not nested JSON strings. That would be
"PARAMS": "[{\"TRAN_IND\":\"current\"},{\"TRAN_TYP\":\"Debit\"},{\"country\":\"US\"}]"
so "text" parts are surrounded by "-s inside (which have to be escaped as \"-s).
In that case you could write
String json=
"{\n"+
" \"data\": [\n"+
" {\n"+
" \"CUST_ID\": \"CUST7\",\n"+
" \"EXPRY_DATE\": null,\n"+
" \"PARAMS\": \"[{\\\"TRAN_IND\\\":\\\"savings\\\"},{\\\"TRAN_TYP\\\":\\\"Debit\\\"},{\\\"country\\\":\\\"US\\\"}]\"\n"+
" },\n"+
" {\n"+
" \"CUST_ID\": \"CUST8\",\n"+
" \"EXPRY_DATE\": null,\n"+
" \"PARAMS\": \"[{\\\"TRAN_IND\\\":\\\"current\\\"},{\\\"TRAN_TYP\\\":\\\"Debit\\\"},{\\\"country\\\":\\\"US\\\"}]\"\n"+
" }\n"+
" ]\n"+
"}";
// Print input for clarity:
System.out.println(json);
JSONObject data= (JSONObject)JSONValue.parse(json);
JSONArray jsonObj = (JSONArray)data.get("data");
JSONObject JsonRow = (JSONObject)jsonObj.get(0);
// parse nested JSON
JSONArray servParam= (JSONArray)JSONValue.parse((String)JsonRow.get("PARAMS"));
// array element is an object ({"TRAN_IND":"savings"}), so toString has to be used:
String tran_ind=servParam.get(0).toString();
System.out.println(tran_ind);
(The backslash-heaps are there because double-quotes had to be escaped in source code, and also the suggested escaped double quotes. So they would not appear in a JSON file. Try the code in action, it prints the JSON it works on)
So (JSONArray)JSONValue.parse((String)JsonRow.get("PARAMS")) would get and parse the nested JSON.
But now you either have to rework the code what generates your input, or parse the nested non-JSON manually.
You can use below code for parsing.
String servParam = (String) JsonRow.get("PARAMS");
String servParamSplitted[] = servParam.substring(1, servParam.length() - 1).split(",");
String traind_id[] = servParamSplitted[0].substring(1, servParamSplitted[0].length() - 1).split(":");
String train_id=traind_id[1];
I like to add that your JSON should be like below format.
{
"data": [
{
"CUST_ID": "CUST7",
"EXPRY_DATE": null,
"PARAMS": [{"TRAN_IND":"savings"},{"TRAN_TYP":"Debit"},{"country":"US"}]
},
{
"CUST_ID": "CUST8",
"EXPRY_DATE": null,
"PARAMS": [{"TRAN_IND":"current"},{"TRAN_TYP":"Debit"},{"country":"US"}]
}
]
}
So, we can parse it using below code.
JSONArray servParam = (JSONArray) JsonRow.get("PARAMS");
JSONObject jsonObjectTrainID = (JSONObject) servParam.get(0);
String TrainIDValue = (String) jsonObjectTrainID.get("TRAN_IND");

Categories