How to get count all json nodes using Jackson framework - java

Here is my user.json
{
"id":1,
"name":{
"first":"Yong",
"last":"Mook Kim"
},
"contact":[
{
"type":"phone/home",
"ref":"111-111-1234"
},
{
"type":"phone/work",
"ref":"222-222-2222"
}
]
},
{
"id":2,
"name":{
"first":"minu",
"last":"Zi Lap"
},
"contact":[
{
"type":"phone/home",
"ref":"333-333-1234"
},
{
"type":"phone/work",
"ref":"444-444-4444"
}
]
}
I would like count how many json object is in there. For example the above json has 2 json object id = 1 and id =2.
//tree model approach
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(new File("user.json"));
List<JsonNode> listOfNodes = rootNode.findParents("first");
System.out.println(listOfNodes.size());
Giving me size = 1.
Can you please tell me what i am doing wrong?
Thanks

Your java code is correct but your json file is invalid.
Jackson parses only first valid element ("Yong").
To fix this just add [ at the begining and ] at the end of file (make it array).

Related

How to replace json node in jsonNode or ObjectNode

I have a JSON node-like below. The structure of JsonNode will change dynamically.
Now I want to replace/update the value of a particular key.
Sample JSON One
{
"company": "xyz",
"employee": {
"name": "abc",
"address": {
"zipcode": "021566"
}
}
}
Sample JSON Two
{
"name": "abc",
"address": {
"zipcode": "021566"
}
}
I want to replace the zip code value 021566 to 566258. I know key name (zipcode), old and new zip code value but I don't know the path of zip code. I tried multiple ways using com.fasterxml.jackson.databind.JsonNode - put, replace
Is there any way to update in java?
JsonNodes are immutable, but you can find the value you want from a JsonNode, cast the original to an ObjectNode, replace the value, then cast that back to a JsonNode. It's a little odd, I know, but it worked for me.
public static void findAndReplaceJsonNode throws JsonProcessingException {
String jsonOne = "{ \"company\" : \"xyz\", \"address\" : { \"zipcode\" : \"021566\", \"state\" : \"FL\" } }";
String jsonTwo = "{ \"company\" : \"abc\", \"address\" : { \"zipcode\" : \"566258\", \"state\" : \"FL\" } }";
ObjectMapper mapper = new ObjectMapper();
JsonNode nodeOne = mapper.readTree(jsonOne);
JsonNode nodeTwo = mapper.readTree(jsonTwo);
JsonNode findNode = nodeTwo.get("address");
ObjectNode objNode = (ObjectNode) nodeOne;
objNode.replace("address", findNode);
nodeOne = (JsonNode) objNode;
System.out.println(nodeOne);
}
Output:
{"company":"xyz","address":{"zipcode":"566258","state":"FL"}}
Disclaimer: While I do some JSON parsing and processing on a regular basis, I certainly wouldn't say that I'm adept at it or tree traversals with them. There is more than likely a better way to find the value of a child in a JsonNode than by taking the entire child as a node, replacing it's one value and then replacing the node. This should work for you in a pinch, though :)

Adding changes to the JSON structure

I have the following JSON, generated in the Android application:
{
"Details": {
"ClaimDate": "08/10/2019",
"HFCode": "55555"
},
"Items": [
{
"Item": {
"ItemCode": "Y203",
"ItemPrice": "20",
"ItemQuantity": "1"
}
}
],
"Services": [
{
"Service": {
"ServiceCode": "X105",
"ServicePrice": "200",
"ServiceQuantity": "1"
}
}
]
}
On the server side, I need this structure
{
"details": {
"ClaimDate": "08/10/2019",
"HFCode": "55555"
},
"items": [
{
"itemCode": "Y200",
"itemPrice": 0,
"itemQuantity": 0
}
],
"services": [
{
"serviceCode": "X100",
"servicePrice": 0,
"serviceQuantity": 0
}
]
}
Is there a way to customize this on the Android application side?
I try to do it manually, but I can't get a satisfactory result
You can use a transformer function which will take the first json/object as input and returns the second json/object as output. Unfortunately, since your keys and data types are different, standard libraries will not able to do this. If you want to use Jackson or Gson, you will have to play with Custom (De) Serializers.
If you are using Jackson (One of the most popular JSON libraries) and you just want to transform the given JSON string into another one, then you can achieve this by following way:
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(jsonStr);
ObjectNode rootNew = mapper.createObjectNode();
rootNew.put("details", root.get("Details"));
JsonNode itemNode = root.get("Items").get(0).get("Item");
ObjectNode itemsNodeNew = mapper.createObjectNode();
itemsNodeNew.put("itemCode", itemNode.get("ItemCode"));
itemsNodeNew.put("itemPrice", itemNode.get("ItemPrice"));
itemsNodeNew.put("itemQuantity", itemNode.get("ItemQuantity"));
rootNew.put("items", mapper.createArrayNode().add(itemsNodeNew));
JsonNode serviceNode = root.get("Services").get(0).get("Service");
ObjectNode serviceNodeNew = mapper.createObjectNode();
serviceNodeNew.put("serviceCode", serviceNode.get("ServiceCode"));
serviceNodeNew.put("servicePrice", serviceNode.get("ServicePrice"));
serviceNodeNew.put("serviceQuantity", serviceNode.get("ServiceQuantity"));
rootNew.put("services", mapper.createArrayNode().add(serviceNodeNew));
System.out.println(rootNew.toString());
But if you want to convert the JSON string to POJO for further manipulation, you can directly deserialize and serialize it.

LibGDX Json parser - parse specific node/object

I'm currently implementing JSON parsing in my game but I've encountered a problem that I can't find a solution for: how do you parse a specific node/object (not sure what to call it) from a JSON file? Let's say my JSON looks like this:
{
"intro/credits": { //A node/object.
"title": "Intro music / Credits music",
"authors": [
{
"name": "Vindsvept",
"links": {
"YouTube": "https://www.youtube.com/channel/UCfSUheoljDlGDjerRylO4Nw",
"Bandcamp": "https://vindsvept.bandcamp.com/"
}
}
]
},
"extra": { //Another node/object.
"title": "extra",
"authors": [
{
"name": "extra",
"links": {
"linkTest": "linkTest"
}
}
]
}
}
With that JSON in mind, how would I do something like this?:
MyObject myObj = json.fromJson(parse.object.called.extra);
Thanks to Underbalanced I can now answer my own question: to exctract an object called extra you would do something like this:
Json json = new Json();
JsonValue root = new JsonReader().parse(Gdx.files.internal("path/to/your/file.json"));
JsonValue extra = root.get("extra"); //Replace 'extra' with whatever your object is called.
MyObject myObj = json.fromJson(MyObject.class, extra.toString());

read json file and parse inner json array in java

{
"vers": 0.01,
"config": {
"rate": "perhr",
"valueColumns": [
"vCPU",
"ECU",
"memoryGiB",
"storageGB",
"linux"
],
"currencies": [
"USD"
],
"regions": [
{
"region": "us-east",
"instanceTypes": [
{
"type": "generalCurrentGen",
"sizes": [
{
"size": "t2.micro",
"vCPU": "1",
"ECU": "variable",
"memoryGiB": "1",
"storageGB": "ebsonly",
"valueColumns": [
{
"name": "linux",
"prices": {
"USD": "0.013"
}
}
]
},
{
"size": "t2.small",
"vCPU": "1",
"ECU": "variable",
"memoryGiB": "2",
"storageGB": "ebsonly",
"valueColumns": [
{
"name": "linux",
"prices": {
"USD": "0.026"
}
}
]
}
]
}
]
}
]
}
}
Hi, i wanted to read this json file. I tried various ways from google but getting a null at valuesColumns. I have to read sizes array and have to put in list.
I think it will help your cause if you format your json. As it is it's quite hard to read. Googling for a JSON beautifier quickly found me this one.
When working with JSON your browser console provides a nice environment for inspecting and playing with the data. I pasted it into the browser console and did (hit enter after each line):
var x = { ... paste JSON here ... }
x
x.config
x.config.valueColumns
This tells me that x is a JSON object, config is a JSON object and valueColumns is a JSON array
Now to java. Grab yourself a json library, and accessing valueColumns will be something like:
JSONObject x = new JSONObject("{ ... JSON string ... }");
JSONObject config = x.getJSONObject("config");
JSONArray valueColumns = config.getJSONArray("valueColumns");
You can then iterate over valueColumns and pull out what you need.
Note that the above only gets you to the first valueColumns array under config. By following the same principle you can go deeper into the structure and get out the valueColumns for the objects in the sizes array if that's what you're really after.
For parsing json to java there are simple step.
Below code snippet may help you.
// parse json to java
Object obj = parser.parse(s);
JSONObject json = (JSONObject) obj;
JSONObject o = (JSONObject) json.get("config");
//get json array.
JSONArray array = (JSONArray) o.get("valueColumns");
System.out.println(array.toJSONString());
//access element by index
System.out.println(array.get(0));

Insert value into ObjectNode and return JsonNode in Jackson json library

I am trying to insert a value into a json object in the following format and save it to the database.
{
"mainObject": {
"childObject1": {
"validator": {
"dataType": "TEXT",
"regEx": "^[a-zA-Z0-9_]*{3,10}$"
},
"input": "Enter data value here"
},
"childObject2": {
"validator": {
"dataType": "TEXT",
"regEx": "^[a-zA-Z0-9_]*{3,10}$"
},
"input": "Enter data value here"
}
}
}
I need to enter values in the tag where it says input. Something like this:
{
"mainObject": {
"childObject1": {
"validator": {
"dataType": "TEXT",
"regEx": "^[a-zA-Z0-9_]*{3,10}$"
},
"input": "Input 1"
},
"childObject2": {
"validator": {
"dataType": "TEXT",
"regEx": "^[a-zA-Z0-9_]*{3,10}$"
},
"input": "Input 2"
}
}
}
I have tried the following code snippet in java. I am able to insert data into the right node.
String output = "{
\"mainObject\": {
\"childObject1\": {
\"validator\": {
\"dataType\": \"TEXT\",
\"regEx\": \"^[a-zA-Z0-9_]*{3,10}$\"
},
\"input\": \"Enter data value here\"
},
\"childObject2\": {
\"validator\": {
\"dataType\": \"TEXT\",
\"regEx\": \"^[a-zA-Z0-9_]*{3,10}$\"
},
\"input\": \"Enter data value here\"
}
}
}";
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(output);
ObjectNode newMetadata = (ObjectNode) rootNode.path("mainObject").path("childObject1");
newMetadata.put("inputValue", "Input 1");
My problem is how to update and write this back to the mainObject node. At the moment the child nodes input tag is updated with the value, i want to update the mainobject with this and save to database.
I have already pasted the code that had the answer. I was looking at the wrong node. I mentioned in my previous comment, I didn't really see an option to close the question. To make it clear, the answer was that as soon as I write to the child nodes, the parent node will have the property as well. That is working code which does not really need a fix, as I said I was looking at the wrong node.

Categories