Parse only particular fields in JSON at once - java

I have a huge JSON but I only need to parse specific fields. I know paths to these fields so I decided to try JPath and it works but I want to parse all fields at once.
Let's say I have such JSON:
{
"data": [
{
"field1": 1,
"field2": 1,
...
"another_data": [ {
"required_field1": "1",
"required_field2": "2"
}
],
...
}
]
}
I want to get only required fields with these paths and map it to Java POJO:
$.data[*].another_data[*].required_field1
$.data[*].another_data[*].required_field2
So as a final result I want to have a list of Java objects, where the object contains required_field1 and required_field2.
UPD:
how it works now
I have a Java POJO that's a container
class RequiredInfo {
private String field1;
private String field2;
//constructor, setters, etc
}
I read JSON path 2 times by using JPath:
String json = "...";
Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);
List<String> reqFields1 = JsonPath.read(document, "$.data[*].another_data[*].required_field1");
List<String> reqFields2 = JsonPath.read(document, "$.data[*].another_data[*].required_field2")
and then I map it to my POJO
for (int i = 0; i < reqFields1.size(); i++) {
res.add(new RequiredInfo(reqFields1.get(i), reqFields2.get(i)));
}
bit I think there is a better way how I can do it

You can try by creating a JSON object and get data:
JSONObject yourJsonObject = (JSONObject) new JSONParser().parse(yourJson);
JSONObject data = (JSONObject) yourJsonObject.get("data");
JSONObject data0 = (JSONObject) data.get(0);
JSONObject another_data = (JSONObject) data0.get("another_data");
String required_field1 = another_data.get("required_field1").toString();
String required_field2 = another_data.get("required_field2").toString();
Now that you have values, you can add them in your POJOs.

Related

Nested JSONArray

I need to read a JSON file with following form:
{
"Data":[{
"foo":"22",
"bar":"33",
"array":[
{
"1foo":"22",
"1bar":"33"
},
{
"2foo":"22",
"2bar":"33",
}
],
"anotherData":{
"foofoo":"22",
"barbar":"33"
},
"some more data":"11",
"some more data":"11"
},
{and the cycle here starts again from -->
"foo":"22",
"bar":"33",
"array":[
My question stands : How do I access individual elements given it's sometimes JSONObject and sometimes JSONArray. I tried using org.json library but I'm failing to access anything after this line -> "array":[. I tried various combinations of JSONObject and JSONArray up to no avail.
My latest code looked something like this:
List<Data> data= new ArrayList<>();
String rawJson = getJsonAsString();
JSONObject outer = new JSONObject(rawJson);
JSONArray jArr= outer.getJSONArray("Data");
JSONObject inner= outer.getJSONObject("array");
for(int i =0; i<jArr.length(); i++){
JSONObject jsonEvent = jArr.getJSONObject(i);
String foo = jsonEvent.getString("foo"); <-- this works,
String 1foo = jsonEvent.getString("1foo"); <-- but this doesn't and i cant access it
I tried dozens of different solutions(tried myself and tried to find something here as well, but every case with those nested arrays is different and I can't add those solutions together to get answer for my case)
You can increase your readability if you beautify your raw JSON string:
{
"Data":[
{
"foo":"22",
"bar":"33",
"array":[
{
"1foo":"22",
"1bar":"33"
},
{
"2foo":"22",
"2bar":"33"
}
],
"anotherData":{
"foofoo":"22",
"barbar":"33"
},
"some more data":"11",
"some more data":"11"
},
{ and the cycle here starts again from -->
"foo":"22",
"bar":"33",
"array":[
...
],
...
}
]
}
So, stick to the following code:
JSONArray jArr = outer.getJSONArray("Data");
jArr is now filled with array of your Object.
And to loop through your Object array, you can use a for-loop which you have done it correctly.
for (int i = 0; i < jArr.length(); i++) {
// The below gets your Object
JSONObject jsonEvent = jArr.getJSONObject(i);
}
And now each jsonEvent contains your Object, which you can access the Object by their type.
For example, if you would like to access foo, you can use:
String foo = jsonEvent.getString("foo"); // foo = "22"
String bar = jsonEvent.getString("bar"); // bar = "33"
// Note that your array is another Array, you need to get it as JSONArray first
JSONArray arrayJson = jsonEvent.getJSONArray("array");
And as 1foo is in the first Object for your array, you need to access it like this:
JSONObject firstObjectInArray = arrayJson.getJSONObject(0);
String target = firstObjectInArray.getString("1foo"); // target = "22"
And to access foofoo, as it is an attribute of the JSON Object anotherData, so you should obtain anotherData as JSONObject first, and then you can access foofoo:
JSONObject anotherDataObject = jsonEvent.getJSONObject("anotherData");
String foofoo = anotherDataObject.getString("foofoo"); // foofoo = "22"
So the full code within your for-loop should look like this:
for (int i = 0; i < jArr.length(); i++) {
// The below gets your Object
JSONObject jsonEvent = jArr.getJSONObject(i);
String foo = jsonEvent.getString("foo");
JSONArray arrayJson = jsonEvent.getJSONArray("array");
String target = arrayJson.getJSONObject(0).getString("1foo");
// Add to get foofoo
JSONObject anotherDataObject = jsonEvent.getJSONObject("anotherData");
String foofoo = anotherDataObject.getString("foofoo");
}

Gson fromJson deserialize

I have the following json:
[
{
"": "",
"substituted_restday": "2020-02-01",
"original_restday": "2020-02-08",
"id": "15d13f70-c0a852c0-3a925f13-6dca1982",
"_UNIQUEKEY_": "15d1592a-c0a852c0-3a925f13b7c65023",
"parentId": ""
},
{
"": "",
"substituted_restday": "2020-02-03",
"original_restday": "2020-02-09",
"id": "15d14d55-c0a852c0-3a925f13-727b70af",
"_UNIQUEKEY_": "15d1592a-c0a852c0-3a925f13-3711a584",
"parentId": ""
}
]
I want to get the value of "substituted_restday" and "original_restday" from the JSON. So I used gson.from with the following syntax to concert it into JAVA object.
String[] str = gson.fromJson(JSON, String[].class);
However, it showed the following error:
com.google.gson.JsonParseException: The JsonDeserializer StringTypeAdapter failed to deserialize json object {"":"","substituted_restday":"2020-02-01","original_restday":"2020-02-08","id":"15d13f70-c0a852c0-3a925f13-6dca1982","_UNIQUEKEY_":"15d1592a-c0a852c0-3a925f13-b7c65023","parentId":""} given the type class java.lang.String
So, how can I get the value of "substituted_restday" and "original_restday" from the JSON? Thank you?
Tree Structure
Gson can parse the JSON into a tree structure, similar to how XML can be parsed into a DOM tree. The nodes of the tree can be one of these subclasses of JsonElement: JsonObject, JsonArray, JsonPrimitive, and JsonNull.
Since the JSON starts with a [, you can parse into a JsonArray, like this:
JsonArray root = gson.fromJson(JSON, JsonArray.class);
for (JsonElement elem : root) {
JsonObject obj = elem.getAsJsonObject();
String substituted_restday = obj.get("substituted_restday").getAsString();
String original_restday = obj.get("original_restday").getAsString();
System.out.printf("substituted_restday = '%s', original_restday = '%s'%n",
substituted_restday, original_restday);
}
List of Maps
Gson can parse the JSON objects into a Map.
List<Map<String, String>> root = gson.fromJson(JSON, new TypeToken<List<Map<String, String>>>() {}.getType());
for (Map<String, String> obj : root) {
String substituted_restday = obj.get("substituted_restday");
String original_restday = obj.get("original_restday");
System.out.printf("substituted_restday = '%s', original_restday = '%s'%n",
substituted_restday, original_restday);
}
Array of POJOs
Gson can parse the JSON objects into POJOs. This is the most type-safe way to handle the data.
MyObj[] root = gson.fromJson(JSON, MyObj[].class);
for (MyObj obj : root) {
System.out.printf("substituted_restday = '%s', original_restday = '%s'%n",
obj.substitutedRestday, obj.originalRestday);
}
class MyObj {
#SerializedName("")
String blank;
#SerializedName("substituted_restday")
String substitutedRestday;
#SerializedName("original_restday")
String originalRestday;
#SerializedName("id")
String id;
#SerializedName("_UNIQUEKEY_")
String uniqueKey;
#SerializedName("parentId")
String parentId;
}
You would likely want getter and setter methods on your POJO. This is just a simplified running example.
Output (from all 3)
substituted_restday = '2020-02-01', original_restday = '2020-02-08'
substituted_restday = '2020-02-03', original_restday = '2020-02-09'
JsonObject jsonObject = gson.fromJson( JSON, JsonObject.class);
then
jsonObject.get(substituted_restday); // returns a JsonElement for that name
jsonObject.get(original_restday);
Imo, you should create a pojo for the json element and then have fromJson method return an array of that pojo's. This link should give you more details - https://howtodoinjava.com/gson/gson-parse-json-array/

how to fetch JSONObject with array of objects

I have json string data like:
{"contactlist":["{"id":"1","mobile":"186010855","name":"Intex"}","{"id":"212","mobile":"980067","name":"pari"}"]}
I want to fetch all data means id,mobile and name for all..
So, I have Contact Class :
public class Contact {
private String id;
private String name;
private String mobile;
//getters and settrs & constructors
}
and for fetching I have tried:
String stringdata=
"{"contactlist":["{"id":"1","mobile":"186010855","name":"Intex"}","
{"id":"212","mobile":"980067","name":"pari"}"]}";
try{
Contact contact1 = new Contact();
contact1 = new Gson().fromJson(contactreceive, Contact.class);
Contact contact = new Contact(contact1.getId(),contact1.getName(),
contact1.getMobile());
System.out.println (contact);
}catch(Exception e){
}
But I can not fetch data like this..how can I fetch this json data?
Your JSON is invalid, as per #ShubhamChaurasia 's comment. The following JSON validates:
{
"contactlist": [{
"id": "1",
"mobile": "186010855",
"name": "Intex"
},
{
"id": "212",
"mobile": "980067",
"name": "pari"
}]
}
Escape this in Java as you have already been shown (with \") and this will stop your JSON validation errors. I recommend combining this with #Joopkins ' or #JanTheGun 's answer.
A good site I use for JSON validation is http://jsonlint.com/.
You need to escape the double quotes to get a valid json string. Then you can read the json array like this:
String stringdata = "{\"contactlist\":[{\"id\":\"1\",\"mobile\":\"186010855\",\"name\":\"Intex\"},{\"id\":\"212\",\"mobile\":\"980067\",\"name\":\"pari\"}]}";
JsonElement jsonElement = new JsonParser().parse(stringdata);
JsonObject jsonOject = jsonElement.getAsJsonObject();
JsonArray jsonArray = jsonOject.getAsJsonArray("contactlist");
for (JsonElement element : jsonArray) {
JsonObject obj = element.getAsJsonObject();
String id = obj.get("id").toString();
String name = obj.get("name").toString();
String mobile = obj.get("mobile").toString();
Contact contact = new Contact(id, name, mobile);
System.out.println("id: " + contact.getId());
System.out.println("name: " + contact.getName());
System.out.println("mobile: " + contact.getMobile());
System.out.println("");
}
You can convert the stringdata into a JSONArray containing a JSONObject for each contact.
JSONObject contactData = new JSONObject(stringdata);
JSONArray contactArray = contactData.getJSONArray("contactlist");
//Create an array of contacts to store the data
Contact[] contacts = new Contact[contactArray.length()];
//Step through the array of JSONObjects and convert them to your Java class
Gson gson = new Gson();
for(int i = 0; i < contactArray.length(); i++){
contacts[i] = gson.fromJson(
contactArray.getJSONObject(i).toString(), Contact.class);
}
Now you have an array of Contacts from your raw JSON data.
JSONObject contactData = new JSONObject(stringdata);
JSONArray contactArray = contactData.getJSONArray("contactlist");
for(int i=0;i<contactArray .length;i++){
JSONObject jsonObject=contactArray.getJSONObject(i));
String id=jsonObject.getString("id")
String key=jsonObject.getString("key")
}

How to iterate JSON Array and extract each JSON Object from it using GSON?

Below is my JSON String which I am getting back by calling from a service API. I have shorten it down by having only three reportRecords for the understanding purpose. In general, it might have ~500 reportRecords
{
   "aggRecords": {
      "reportRecords": [
         {
            "min": 0,
            "max": 12,
            "avg": 0.3699187,
            "count": 246,
            "sumSq": 571,
            "stddev": 1.4779372,
            "median": 0,
            "percentileMap": {
               "95": 4
            },
            "metricName": "TransactionDuration",
            "dimensions": {
               "env": "dev",
               "pool": "titan",
               "Name": "PostProcessing",
               "Type": "PostProcessing"
            },
            "value": 91
         },
         {
            "min": 0,
            "max": 23,
            "avg": 2.3991289E-4,
            "count": 1463031,
            "sumSq": 3071,
            "stddev": 0.045814946,
            "median": 0,
            "percentileMap": {
               "95": 0
            },
            "metricName": "TransactionDuration",
            "dimensions": {
               "env": "dev",
               "pool": "titan",
               "Name": "ResourceContext",
               "Type": "ResourceContext"
            },
            "value": 351
         },
         {
            "min": 0,
            "max": 1209,
            "avg": 1.9203402,
            "count": 7344636,
            "sumSq": 71832774,
            "stddev": 2.4683187,
            "median": 2,
            "percentileMap": {
               "95": 4
            },
            "metricName": "TransactionDuration",
            "dimensions": {
               "env": "dev",
               "pool": "titan",
               "Name": "Client::Sync",
               "Type": "Client::Sync"
            },
            "value": 14104200
         }
      ]
   },
   "minRecordsMap": {}
}
Now From the above JSON response, I need to extract reportRecords whose Name is Client::Sync. Meaning, I need to extract below reportRecords from the above JSON response only.
         {
            "min": 0,
            "max": 1209,
            "avg": 1.9203402,
            "count": 7344636,
            "sumSq": 71832774,
            "stddev": 2.4683187,
            "median": 2,
            "percentileMap": {
               "95": 4
            },
            "metricName": "TransactionDuration",
            "dimensions": {
               "env": "dev",
               "pool": "titan",
               "Name": "Client::Sync",
               "Type": "Client::Sync"
            },
            "value": 14104200
         }
And now I need to parse the above reportRecords for Client::Sync to below object -
public class DataMetrics {
private String pool;
private String name;
private String type;
private String env;
private String metricName;
private String percentile;
private String median;
private String stdDev;
private String sumSq;
private String count;
private String avg;
private String max;
private String min;
// getters and setters here
}
Above variable, maps like this -
pool is titan
name is Client::Sync
type is Client::Sync
env is dev
metricNname is TransactionDuration
95th percentile is 4
median is 2
stdDev is 2.4683187
sumSq is 71832774
count is 7344636
avg is 1.9203402
max is 1209
min is 0
I am using GSON library here and below is what I have tried so far -
private static RestTemplate restTemplate = new RestTemplate();
public static void main(String[] args) {
String jsonLine = restTemplate.getForObject("some_url", String.class);
System.out.println(jsonLine); // here jsonLine will give me above big JSON String
JsonElement jelement = new JsonParser().parse(jsonLine);
JsonObject jobject = jelement.getAsJsonObject();
jobject = jobject.getAsJsonObject("aggRecords");
JsonArray jarray = jobject.getAsJsonArray("reportRecords");
// now how do I iterate JsonArray and get each JSON object
// and then check "name" property of each object, if "Client::Sync" found, read that object for all properties
// and set it using setters.
}
Now I am not able to understand how do I iterate JsonArray and extract each JSON object from it?
So you have the JsonArray object with your records, here's what you do to get your functional objects:
Type type = new TypeToken<List<DataMetrics>>() {}.getType();
List<DataMetrics> records = gson.fromJson(jsonArrayThatYouHave, type);
Then you iterate through you objects and filter the ones you need.
In java 8 you can do this:
List<DataMetrics> result = records.stream().filter(record -> record.name.equals("Client::Sync")).collect(toList());
This approach is converting all objects and iterating after, if exactly this part of code is performance critical, you can still iterate through json and convert only necessary objects (but i doubt that this will be actually faster than described above).
Anyway this is more maintainable and understandable code.
UPDATE:
the same for java 7 will be:
List<DataMetrics> result = new LinkedList<>();
for(DataMetrics record : records){
if(record.name.equals("Client::Sync")){
result.add(record);
}
}
Or if you want to iterate json and parse only required ones heres what you can do:
Type type = new TypeToken<List<DataMetrics>>() {}.getType();
for(JsonElement elem : jsonArrayThatYouHave) {
if (elem.getAsJsonObject().get("name").getAsString().equals("Client::Sync")) {
result.add(gson.fromJson(elem, type));
}
}
but I dont think this is actually faster than the first one because in both cases you are converting json to java functional object with parser and getting JsonArray or anything else. Taking into consideration the fact that both are Googles libs, i assume that parsing from JsonObject to some specific type with gson is way faster than from String (raw json) to the same specific type...
You may want to parse all the objects, and then filter the ones you're interested in.
After you've obtained jArray, try:
//get json array from json string
JsonArray jarray = jobject.getAsJsonArray("reportRecords");
//get a list of reportRecords using Gson
Gson mGson = new Gson();
Type listType = new TypeToken<List<DataMetrics>>(){}.getType();
List<DataMetrics> dataMetricsList = mGson.fromJson(reportRecordsJsonArray, listType);
//Filter only the ones with a specific name
List<DataMetrics> dataMetricsFilteredList = dataMetricsList.stream().filter(dataMetric -> dateMetric.getName.equals("Client::Sync"));
i didn't try it but it may work.
public void getFromJson(JSONObject json)
{
JSONArray jarray = (JSONArray) json.get("reportRecords");
List<DataMetrics> myList = new ArrayList();
for(int i = 0; i < jarray.size(); i++)
{
myList.add((DataMetrics) getClassFromJsonObject((JSONObject) jarray.get(i),
DataMetrics.class));
}
}
////
public Object getClassFromJsonObject(JSONObject json, Class myClass){
Object object = new Object();
ObjectMapper obj = JSONMapperFactory.createMapper();
obj.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
object = obj.readValue(json.toString(), myClass);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return myClass.cast(object);
}

Getting JSONObject from JSONArray [duplicate]

This question already has answers here:
Accessing members of items in a JSONArray with Java
(6 answers)
Closed 6 years ago.
I am in a bit of a fix regarding the JSONObject that I am getting as a response from the server.
jsonObj = new JSONObject(resultString);
JSONObject sync_reponse = jsonObj.getJSONObject("syncresponse");
String synckey_string = sync_reponse.getString("synckey");
JSONArray createdtrs_array = sync_reponse.getJSONArray("createdtrs");
JSONArray modtrs_array = sync_reponse.getJSONArray("modtrs");
JSONArray deletedtrs_array = sync_reponse.getJSONArray("deletedtrs");
String deleted_string = deletedtrs_array.toString();
{"syncresponse":{"synckey":"2011-09-30 14:52:00","createdtrs":[],"modtrs":[],"deletedtrs":[{"companyid":"UTB17","username":"DA","date":"2011-09-26","reportid":"31341"}]
as you can see in the response that I am getting I am parsing the JSONObject and creating syncresponse, synckey as a JSON object createdtrs, modtrs, deletedtrs as a JSONArray. I want to access the JSONObject from deletedtrs, so that I can split them apart and use the values. i.e I want to extract companyid, username, date etc.
How can I go about this ?
Thanks for your input.
JSONArray objects have a function getJSONObject(int index), you can loop through all of the JSONObjects by writing a simple for-loop:
JSONArray array;
for(int n = 0; n < array.length(); n++)
{
JSONObject object = array.getJSONObject(n);
// do some stuff....
}
Here is your json:
{
"syncresponse": {
"synckey": "2011-09-30 14:52:00",
"createdtrs": [
],
"modtrs": [
],
"deletedtrs": [
{
"companyid": "UTB17",
"username": "DA",
"date": "2011-09-26",
"reportid": "31341"
}
]
}
}
and it's parsing:
JSONObject object = new JSONObject(result);
String syncresponse = object.getString("syncresponse");
JSONObject object2 = new JSONObject(syncresponse);
String synckey = object2.getString("synckey");
JSONArray jArray1 = object2.getJSONArray("createdtrs");
JSONArray jArray2 = object2.getJSONArray("modtrs");
JSONArray jArray3 = object2.getJSONArray("deletedtrs");
for(int i = 0; i < jArray3 .length(); i++)
{
JSONObject object3 = jArray3.getJSONObject(i);
String comp_id = object3.getString("companyid");
String username = object3.getString("username");
String date = object3.getString("date");
String report_id = object3.getString("reportid");
}
JSONArray deletedtrs_array = sync_reponse.getJSONArray("deletedtrs");
for(int i = 0; deletedtrs_array.length(); i++){
JSONObject myObj = deletedtrs_array.getJSONObject(i);
}
{"syncresponse":{"synckey":"2011-09-30 14:52:00","createdtrs":[],"modtrs":[],"deletedtrs":[{"companyid":"UTB17","username":"DA","date":"2011-09-26","reportid":"31341"}]
The get companyid, username, date;
jsonObj.syncresponse.deletedtrs[0].companyid
jsonObj.syncresponse.deletedtrs[0].username
jsonObj.syncresponse.deletedtrs[0].date
start from
JSONArray deletedtrs_array = sync_reponse.getJSONArray("deletedtrs");
you can iterate through JSONArray and use values directly or create Objects of your own type
which will handle data fields inside of each deletedtrs_array member
Iterating
for(int i = 0; i < deletedtrs_array.length(); i++){
JSONObject obj = deletedtrs_array.getJSONObject(i);
Log.d("Item no."+i, obj.toString());
// create object of type DeletedTrsWrapper like this
DeletedTrsWrapper dtw = new DeletedTrsWrapper(obj);
// String company_id = obj.getString("companyid");
// String username = obj.getString("username");
// String date = obj.getString("date");
// int report_id = obj.getInt("reportid");
}
Own object type
class DeletedTrsWrapper {
public String company_id;
public String username;
public String date;
public int report_id;
public DeletedTrsWrapper(JSONObject obj){
company_id = obj.getString("companyid");
username = obj.getString("username");
date = obj.getString("date");
report_id = obj.getInt("reportid");
}
}
When using google gson library.
var getRowData =
[{
"dayOfWeek": "Sun",
"date": "11-Mar-2012",
"los": "1",
"specialEvent": "",
"lrv": "0"
},
{
"dayOfWeek": "Mon",
"date": "",
"los": "2",
"specialEvent": "",
"lrv": "0.16"
}];
JsonElement root = new JsonParser().parse(request.getParameter("getRowData"));
JsonArray jsonArray = root.getAsJsonArray();
JsonObject jsonObject1 = jsonArray.get(0).getAsJsonObject();
String dayOfWeek = jsonObject1.get("dayOfWeek").toString();
// when using jackson library
JsonFactory f = new JsonFactory();
ObjectMapper mapper = new ObjectMapper();
JsonParser jp = f.createJsonParser(getRowData);
// advance stream to START_ARRAY first:
jp.nextToken();
// and then each time, advance to opening START_OBJECT
while (jp.nextToken() == JsonToken.START_OBJECT) {
Map<String,Object> userData = mapper.readValue(jp, Map.class);
userData.get("dayOfWeek");
// process
// after binding, stream points to closing END_OBJECT
}
Make use of Android Volly library as much as possible. It maps your JSON reponse in respective class objects. You can add getter setter for that response model objects. And then you can access these JSON values/parameter using .operator like normal JAVA Object. It makes response handling very simple.

Categories