How to update nested JSON in Java with dynamic structure - java

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.

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 validate json schema for a particular naming?

Updated:
Please, take a look at following.
For this example, it has two pretty the same objects inside. With two fields for each of them - id and is_deleted.
{
"meta": {
"delete_count": 1,
"status": [
{
"id": 1,
"is_deleted": true
},
{
"id": 2,
"is_deleted": false
}
]
}
}
Let's imagine 2 different occasions:
every id has changed to uid
status has changed to stat, the only is_deleted field has changed to just deleted(if this is possible. let's imagine it is)
So, I have a schema for this payload. But, it checks for field types not for field names.
it uses com.jayway.restassured.module.jsv
JsonObject has a method which returns true if key exist public boolean has(java.lang.String key)
JSONObject jsonObj = new JSONObject(Your_STRING);
if (jsonObj.has("org_id")) {
//Do stuff
}
for more details you can check below -
check key exist
try to verify if org_id exists, the question isn't clear!.

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);
}
}

In Java, how do I most efficiently find an array within a JSON array based on the value of an element of the subarray?

So this is an example piece of JSON data that I'm working with.
{"season":"2016",
"week":"",
"positions":{
"QB":[
{
"id":"2505245",
"esbid":"PAL249055",
"gsisPlayerId":"00-0021429",
"firstName":"Carson",
"lastName":"Palmer",
"teamAbbr":"ARI",
"opponentTeamAbbr":"",
"position":"QB",
"rank":"22",
"statsLine":"",
"stats":
{
"PassYds":false,
"PassTDs":false,
"Int":false,
"RushYds":false,
"RushTDs":false,
"RecYds":false,
"RecTds":false,
"FumTD":false,
"TwoPt":false,
"FumLost":false
},
"pts":"85.00",
"projectedPts":"277.46",
"status":""
},
{
"id":"2495748",
"esbid":"STA482517",
"gsisPlayerId":"00-0025430",
"firstName":"Drew",
"lastName":"Stanton",
"teamAbbr":"ARI",
"opponentTeamAbbr":"",
"position":"QB",
"rank":"42",
"statsLine":"",
"stats":
{
"PassYds":false,
"PassTDs":false,
"Int":false,
"RushYds":false,
"RushTDs":false,
"RecYds":false,
"RecTds":false,
"FumTD":false,
"TwoPt":false,
"FumLost":false
},
"pts":"11.06",
"projectedPts":"7.36",
"status":""}]
}
}
Now I have a huge list with hundreds of different players set up like this and I would like to be able to get the data for a single player. In this case, let's say I want to find the stats for Carson Palmer. That would mean I want to look in the QB JSON array to find a sub array which includes firstName:Carson and lastName:Palmer.
How would I do this with a library like GSON?
JsonPath
From all positions, find all elements with first name Carson, last name Palmer
$.positions[*][?(#.firstName == "Carson" && #.lastName == "Palmer")]
Add .stats to the end of that or parse it out yourself from that object
Note: that returns an array. Multiple players could have that name.
Alternatively, you are getting this data from some server, and you should perform the player search server-side

JSONPath, How to write (create) nested element (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)

Categories

Resources