JSONPath, How to write (create) nested element (Java) - java

I want to create a json file. I know json simple, but the JsonObject and JsonArray aren't fast enough for me. I want the same efficiency as yaml (for finding and writing values with path).
I want to write this example :
{
"test": {
"test1": 564,
"test2": "der",
"list": [
"tes4",
"test5"
]
},
"exList": [
"tes4",
"test5"
]
}
The question is how to write the json part with JsonPath ?
DocumentContext#add doesn't seems to work
DocumentContext#put needs strange args
With this sample code, I'm getting this error:
PathNotFoundException: Missing property in path $['test1']
(Sorry, I'm French.)

What do you mean strange arguments? You can do:
String path = "$"
String key = "newValue"
int value = 1
yourJson.put(path, key, value)

Related

How can I dynamically find the end of an object array inside of a JSON response using GSON?

I am working with a given JSON response. The API I'm using provides responses like such:
{
"data":[
{
"sample-value": "sample"
}
{
"sample-value": "sample"
}
{
"sample-value": "sample"
}
{
"sample-value": "sample"
}
],
"meta": {
"current-page": 1,
"next-page": 2,
"prev-page": null,
"total-pages": 5,
"total-count": 4338,
"filters": {}
},
"links": {
"self": "linktothisquery",
"next": "linktonextquery",
"last": "linktolastpagequery"
}
}
As you can see, the response provided contains what I interpret to be 1 object array (size changes depending on what is being queried) and 2 objects. (data is the array, meta and links are the objects) I have ran into a situation where I need to run multiple requests in order to get the full amount of data required for my project. I'm attempting to get around this by iterating through requests, but due to the variance in response length per-request I cannot use the same logic to locate only the array in the response and thus end up with unexpected characters making GSON unable to parse. I'm currently doing this by using String.substring() and manually inputting the location inside of the response that I want GSON to parse. Basically, I want GSON to ONLY see the "data" array and ignore everything else. I have model classes in my project to serialize the data, but they are built around the objects inside of the afforementioned array and not the array itself.
Your posted JSON is invalid .In data array comma is missing in between two objects. It should be
{
"sample-value": "sample"
},
{
"sample-value": "sample"
}
Now if you just want the data array part you can manually parse it using JsonParser. It will be the easiest way to do it.
String json = "{\"data\":[{\"sample-value\":\"sample\"},{\"sample-value\":\"sample\"},{\"sample-value\":\"sample\"},{\"sample-value\":\"sample\"}],\"meta\":{\"current-page\":1,\"next-page\":2,\"prev-page\":null,\"total-pages\":5,\"total-count\":4338,\"filters\":{}},\"links\":{\"self\":\"linktothisquery\",\"next\":\"linktonextquery\",\"last\":\"linktolastpagequery\"}}";
JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
JsonArray jsonArray = jsonObject.get("data").getAsJsonArray();
jsonArray.forEach(System.out::println);
Output:
{"sample-value":"sample"}
{"sample-value":"sample"}
{"sample-value":"sample"}
{"sample-value":"sample"}

How to update nested JSON in Java with dynamic structure

I have a property file, where the user can define full field names, something like:
league.firstname
league.lastName
Now in my code, I have an incoming JSON, and I want to first retrieve the existing value and then edit the values of fields mentioned in the property file. In this case, retrieve and edit values of league.firstName and league.lastName fields. JSON looks something like:
{
"_internal": {
"pubDateTime": "2017-12-10 11:42:23.504",
"xslt": "xsl/league/roster/marty_active_players.xsl",
"eventName": "league_roster"
},
"league": {
{
"firstName": "Alex",
"lastName": "Abrines",
"personId": "203518",
"teamId": "1610612760"
}
}
}
Now I know I can do something like:
// retrieve values
String fName = jsonObj.getJSONObject("league").getString("firstName");
String lName = jsonObj.getJSONObject("league").getString("lastName");
// put new values
jsonObj.getJSONObject("league").put("firstName", "newVal1");
jsonObj.getJSONObject("league").put("lastName", "newVal2");
But how do I achieve this dynamically. For example, property file is like:
parentObj.child1.child2.child3
and now I want to edit this 4 level deep JSON, so want to do something like:
// how to do the following
String oldVal = jsonObj.getString("parentObj.child1.child2.child3");
jsonObj.put("parentObj.child1.child2.child3", "newVal");
Note:
the level of json depth can be 1 < length < 100.
user can put any relevant value in property file. If the key do not exist in JSON, need to catch exception.
incoming json format is NOT fixed.

How to check if a property exists in a JSONObject without calling .getJSONObject(key) several times?

I'm processing deeply nested JSON data. Here is a shortened example:
{
"timestamp":"123",
"layers":{
"frame_raw":"123",
"frame":{
"frame_frame_interface_id":"0",
"frame_interface_id_frame_interface_name":"asd",
...
},
"eth_raw":"123",
"eth":{
"eth_eth_dst_raw":"asd",
"eth_eth_dst":"asd",
...
},
"ip_raw":"123",
"ip":{
"ip_ip_version_raw":"4",
"ip_ip_version":"4",
"ip_ip_addr_raw":[
"asd",
"asd"
],
"ip_ip_addr":[
"1.1.1.1",
"1.1.1.1"
],
"ip_ip_dst_host":"1.1.1.1"
}
...
}
...
}
I have a list of structures that I explicitly allow. All others should be deleted from the JSON. An example for the list:
###frame###
layers.frame_raw
###eth###
layers.eth.eth_eth_dst
layers.eth.eth_eth_src
###ip###
layers.ip.ip_ip_src
layers.ip.ip_ip_dst
layers.ip.ip_ip_src_host
layers.ip.ip_ip_dst_host
layers.ip.ip_ip_version
layers.ip.ip_ip_hdr_len
layers.ip.ip_ip_dsfield
My problem is that I can only navigate through the JSON structure using "getJSONObject(key)".
How can I generate the path of the lowest elements of my JSON structure in the form "key.key.key..." so that I can match it with my list?
JSON object has a method called .has which will return a boolean value. So the logic is like to check whether the JSON object exists. If so check the child node for more existence of your data. If there is an array you have to get the array and migrate through the array using any loop and do the same. For example:
if (json.has("ip")) {
JSONObject jsonObject = getJSONObject.getString("ip")
String ip_ip_version_raw = jsonObject.getString("ip_ip_version_raw"));
if (jsonObject.has("ip_ip_addr_raw")){
JSONArray ip_ip_addr_raw = jsonObject.getJSONArray("ip_ip_addr_raw");
for (String s : ip_ip_addr_raw) {
...
}
}
}
For reference :
http://developer.android.com/reference/org/json/JSONObject.html#has(java.lang.String)
If you want to check the existence of a property of a JSONObject there is a method called has. This is the link to the official documentation.
I found a solution because the structure in my special case is always layers.layer.property, so the depth of the structure is always the same and not variable.
For interested people:
for (Iterator<String> layersIterator = jsonObject.getJSONObject("layers").keys(); layersIterator.hasNext(); ) {
String layer = layersIterator.next();
for (Iterator<String> propertyIterator = jsonObject.getJSONObject("layers").getJSONObject(layer).keys(); propertyIterator.hasNext(); ) {
String property = propertyIterator.next();
System.out.println("layers."+layer+"."+property);
}
}

Consume complex api data using retrofit [duplicate]

This question already has answers here:
How do I parse JSON in Android? [duplicate]
(3 answers)
Closed 4 years ago.
{"data":
{
"item1": {
"name" : "Box"
"price" : "50"
},
"item2": {
"name" : "Bottle"
"price" : "250"
}, .....
"item20": {
"name" : "Pen"
"price" : "100"
}
}}
This is my API structure. I cannot create separate POJO classes for 20 items as it is not efficient . What is the best way to fetch the name and price of every item and set them to a recycler view?
You will have to change format of your JSON in order to parse it properly. In addition you forgot to put commas after the "name" value.
Option 1:
{
"data":[
{
"name":"Box",
"price":"50"
},
{
"name":"Bottle",
"price":"250"
},
{
"name":"Pen",
"price":"100"
}
]
}
Option 2:
{
"data":{
"item1":{
"name":"Box",
"price":"50"
},
"item2":{
"name":"Bottle",
"price":"250"
},
"item20":{
"name":"Pen",
"price":"100"
}
}
}
Option 1 is the better choice, since you will be able to represent "data" as an array or a list in android (e.g. ArrayList<Data>).
In general i would suggest you to use a parsing library like GSON
Simple, just use GSON to create an object with SerializableNames to hold the json.
Then simply make an arrayList of your gson compatible object.
The rest is just common adapter interactions.
Example of an API return json object that I use. It must match your json structure.
The example is in Kotlin, but it's the same thing for handling json api response.
Create a simple class then do as mentioned in the image
after clicking the Generate option you see the GsonFromat click then a Box will Prompt , If you are unable to see the GsonFormat then download the GsonFormat plugin. This is the simplest way by which you can easily create Pojo class.
put this into the box and click ok it will automatically create the class for you and you can fetch the data.
{
"data":[
{
"name":"Box",
"price":"50"
},
{
"name":"Bottle",
"price":"250"
},
{
"name":"Pen",
"price":"100"
}
]
}

Parse a structured flattened json object to list of object

I am current have a Json like :
{
"data":{
"gatewayId":"asd",
"records":[
{
"ms":123,
"points":[
{
"sensorId":"asdasd",
"sensorType":"asdasd",
"batt" : 12,
"kw" : 2
},
{
"sensorId":"123",
"sensorType":"as123dasd",
"batt" : 12,
"kw" : 2
}
]
},
{
"ms":123123,
"points":[
{
"sensorId":"asdasd",
"sensorType":"asdasd",
"batt" : 12,
"kw" : 2
},
{
"sensorId":"123",
"sensorType":"as123dasd",
"batt" : 12,
"kw" : 2
}
]
}
]
},
"gatewayType":"Asdasd"
}
My purpose is to denormalise the object to the lowest level in Java
where the pojo is
class SimpleData {
private String gatewayId;
private String gatewayType;
private Long ms;
private String sensorType;
private Double batt;
private Long kw;
}
For what I did for now, I flatten the json to a list for string as below.
root.gatewayType="Asdasd"
root.data.gatewayId="asd"
root.data.records[0].ms=123
root.data.records[0].points[0].sensorId="asdasd"
root.data.records[0].points[0].sensorType="asdasd"
root.data.records[0].points[0].batt=12
root.data.records[0].points[0].kw=2
root.data.records[0].points[1].sensorId="123"
root.data.records[0].points[1].sensorType="as123dasd"
root.data.records[0].points[1].batt=12
root.data.records[0].points[1].kw=2
root.data.records[1].ms=123123
root.data.records[1].points[0].sensorId="asdasd"
root.data.records[1].points[0].sensorType="asdasd"
root.data.records[1].points[0].batt=12
root.data.records[1].points[0].kw=2
root.data.records[1].points[1].sensorId="123"
root.data.records[1].points[1].sensorType="as123dasd"
root.data.records[1].points[1].batt=12
root.data.records[1].points[1].kw=2
I am thinking is it any logic or library can parse the above list for string to list of SimpleData object?
Sorry, My question maybe not clear, I find a more simple way to solve the problem.
But I need a library to denormalize the json.
for example if the json is :
{
"a" : "1",
"b" : ["2", "3"]
}
will become
[
{
"a" : "1",
"b" : "2"
},
{
"a" : "1",
"b" : "3"
}
]
I believe the Gson library is what you are looking for. It provides simple methods to convert Json array to simple Java objects, and vice versa. Very handy, developed by Google.
I recommend fastjson, which is really fast and quite easy to use. In your case, you only need to define POJO in the structure as your JSON data and parse the JSON to Object. It's created by Alibaba.

Categories

Resources