I am trying to merge two JsonObjects in java - java

I have JsonObjects fields,obj2.I am trying to add fields in both the objects.
JsonObject fields=commonfields.getJsonObject("fields");
JsonObjet additional=jo.getJsonObject("zas");
fields.put(additional);
Expected outcome should be merged fields of two objects.I am getting errors.

For io.vertx.core.json.JsonObject, you can use mergeIn method.
JsonObject fields = new JsonObject();
fields.putString("a", "1");
fields.putBoolean("b", false);
JsonObject additional = new JsonObject();
additional.putString("c", "1");
additional.putBoolean("d", false);
fields.mergeIn(additional);
System.out.println(fields);`
javax.json.JsonObject provides putAll method, as it implements Map interface.
For other types of JsonObject, which do not implements Map interface you can parse over keys and explicitly put key, value pair in JsonObject.

Related

accessing keys/values in JSONObject in java

In java I have the following code:
import org.json.JSONObject;
JSONObject obj = new JSONObject();
obj.put("firstKey", new JSONObject());
Now in the new object corresponding to the key "firstKey", I want to start inserting new key-value pairs, but I'm not sure how to do this. I've tried oppJSON.get("firstKey").put("one","two"); but this doesn't work - does anyone have any ideas?
JSONObject have specific get methods like getString, getInt, getDouble etc. In your case, you need getJSONObject
oppJSON.getJSONObject("firstKey").put("one","two");
Class JSONObject implements a Map without generics. So while you can use Map<String, String>, JSONObject is the equivalent of Map<Object, Object>. Everything pulled out of it using get has to be cast to its type.
Try ((JSONObject)obj.get("firstKey")).put("one", "two")

Iterate JSON and get fields from JSON

I've tried different solutions but I'm not able to iterate through this JSON and/or get direct specific values.
Could any one help on:
Iterating through all the fields sequentially.
Getting direct access to some fields (eg. when getting this response, access directly to "packet-count" where its value equals 3281).
{"flow-node-inventory:flow":[{"id":"42","priority":10,"table_id":0,"opendaylight-flow-statistics:flow-statistics":{"packet-count":3281,"byte-count":317738,"duration":{"nanosecond":252000000,"second":3432}},"idle-timeout":10000,"cookie":31,"instructions":{"instruction":[{"order":0,"apply-actions":{"action":[{"order":0,"output-action":{"output-node-connector":"1","max-length":0}}]}}]},"match":{"ethernet-match":{"ethernet-source":{"address":"00:00:00:00:00:02"},"ethernet-destination":{"address":"00:00:00:00:00:01"}}},"hard-timeout":50000,"flags":""}]}
I tried to use org.json but any other library would be okay.
You will have to check the structure of your JSON Object and create a structure for the entities you encounter accordingly. For instance, the first thing in your JSON object is an array, so this is the first thing you should care about. Imagine it as a continuous encapsulation. Check the code below for more information.
JSONObject jobj = new JSONObject(stringJson);
JSONArray flowNodeInv = jobj.getJSONArray("flow-node-inventory:flow");
for (int i = 0; i < flowNodeInv.length(); i++){
JSONObject segment = (JSONObject) flowNodeInv.get(i);
JSONObject stats = segment.getJSONObject("opendaylight-flow-statistics:flow-statistics");
int number = stats.getInt("packet-count");
System.out.println("packet-count: "+ number);}
Try This
jObject = new JSONObject(contents.trim());
Iterator<?> keys = jObject.keys();
while( keys.hasNext() ) {
String key = (String)keys.next();
if ( jObject.get(key) instanceof JSONObject ) {
}
}
To get direct access to the fields you can create a Java Object from the JSON String using an ObjectMappet (com.fasterxml.jackson). For example:
ObjectMapper mapper = new ObjectMapper();
MyClass myClass = mapper.readValue(jsonString, MyClass.class);

Inverted order of JSON elements in Java after XML conversion

I'm using the JSON in Java for the transformation of XML to JSON. I have the problem that this implementation is inverting all child elements.
When I pass this XML:
<Person><Child1>a</Child1><Child2>b</Child2></Person>
I will end up with a JSON having the childs inverted:
{"Person":{"Child2":"b", "Child1":"a"}}
My Java code:
JSONObject jsonObject= XML.toJSONObject("<Person><Child1>a</Child1><Child2>b</Child2></Person>");
String myJSONString = jsonObject.toString(4);
How to transform to JSON with keeping the order of the elements (like in XML)?
So my question. How to transform to JSON with keeping the order?
With the current official JSONObject, this is not possible. The API makes it very clear:
A JSONObject is an unordered collection of name/value pairs.
But, there might be a quick workaround for your problem. As from what I've investigated in the JSONObject source code, you can see that it uses a HashMap internally, and as you know HashMap doesn't keep any order.
public JSONObject() {
this.map = new HashMap<String, Object>();
}
You have 2 alternatives:
Modify the current JSONObject source code so that the map is initialized with a LinkedHashMap. A LinkedHashMap is an implementation of the Map interface, with predictable iteration order:
public JSONObject() {
this.map = new LinkedHashMap<String, Object>();
}
Make your own custom class which extends JSONObject but uses a LinkedHashMap internally. Notice that you still have to make some changes in JSONObject.
public class JSONObject {
//private final Map<String,Object> map; // current approach
//you have to remove final modifier and either add a getter or make it protected. I'll choose the change modifier to protected in this case.
protected Map<String,Object> map;
}
public class JSONObjectOrdered extends JSONObject {
public JSONObjectOrdered(){
this.map = new LinkedHashMap <String, Object>();
}
}
As JSONObject is an unordered collection of name/value pairs, no choice, you have to use a JSONArray.
Here is my solution, modify the XML class, particularly the method parse, in order to return JSONArray for storing child nodes.
My modified class : XML.java
XML input
<Person name="test"><Child1>a</Child1><Child2>b</Child2><Child3></Child3></Person>
Usage :
JSONObject jsonObject= XML.toJSONObject("<Person name=\"test\"><Child1>a</Child1><Child2>b</Child2><Child3></Child3></Person>");
System.out.println(jsonObject);
Out :
{"Person":{"CHILDREN":[{"Child1":"a"},{"Child2":"b"},{"Child3":""}],"name":"test"}}
Conclusion
The children order is kept. Off course this idea can be improved, it's just a POC regarding what can be done, modifying the parser.
JSON objects don't have a specific order. You can of course change the serialization implementation to keep an order but there is no guarantee that it is also kept after deserialization. In fact, most JSON libraries won't even have an API to detect in which order the original JSON text was parsed. You shouldn't care about ordering when using objects.
If you do care about the order though, use a JSON array.
{"Person":[{"Child1":"a"},{"Child2":"b"}]}
The JSONObject API dose not guarantee the elements order
A nice solution to this issue can be using JSONArray, in JSONArray the order you insert the elements is saved.
So, in your case you will have an array of "chides" for each person.
you would probably will need to change the XML file or manually parse the XML into the json in your format (the JSONArray instead of what you are using now)
If you are hell bent on getting the output ordered the way you want it you could always try overriding the method
toString()
You can download the source code from http://www.json.org/java/ and modify JSONObject.java using TreeMap instead of HashMap.
You also can override method in JSONObject.java
public Iterator<String> keys() {
return this.keySet().iterator();
}
Make sure the Iterator is the one of the sorted keys.
If you would use Jackson for JSON serialization / deserialization you could simply put a
#JsonPropertyOrder() annotation on top of your class.
#JsonPropertyOrder({"Child1", "Child2"})
public class Person {
#JsonProperty("Child1")
public String child1;
#JsonProperty("Child2")
public String child2;
}
You can keep order of incoming data when modify
private final Map<String, Object> nameValuePairs;
/**
* Creates a {#code JSONObject} with no name/value mappings.
*/
public JSONObject() {
nameValuePairs = new HashMap<String, Object>();
}
to
private final Map<String, Object> nameValuePairs;
/**
* Creates a {#code JSONObject} with no name/value mappings.
*/
public JSONObject() {
nameValuePairs = new LinkedHashMap<String, Object>();
}
Because instead of HashMap - LinkedHashMap have an predictable iteration order.
LinkedHashMap : Hash table and linked list implementation of the Map interface, with predictable iteration order.
So is the most effective way to resolve your problem.
And also you can fork to use a custom library from
https://github.com/SergeyShustikov/JSON-java

JSONObject.append into object - result is nested array?

Following code produces a nested array as a result for keys containing three items:
import org.codehaus.jettison.json.JSONObject;
// ...
JSONObject ret = new JSONObject();
for (Key key:keys) ret.append("blocked",key.id());
The result is:
{"blocked": [[["1"],"2"],"3"]}
Is this expected? If it is, how can I construct a plain array adding item by item?
You need to create a JSONArray object:
JSONObject ret = new JSONObject();
JSONArray arr = new JSONArray();
arr.put("1");
arr.put("2");
arr.put("3");
ret.put("blocked", arr);
The result is:
{"blocked":["1","2","3"]}
It's curious because the API says the following:
Append values to the array under a key. If the key does not exist in the
JSONObject, then the key is put in the JSONObject with its value being a
JSONArray containing the value parameter. If the key was already
associated with a JSONArray, then the value parameter is appended to it.
But it doesn't work correctly. When I do:
JSONObject o = new JSONObject();
o.append("arr", "123");
o.append("arr", "456");
I get an Exception saying that "JSONObject[arr] is not a JSONArray". It looks like there is a bug.
I ran into a similar problem. You should use the put method; not the append method. And, of course, you should create a JSONArrray and use that as the second argument of the put method.

put method in the json object adds value to the first of the jsonobject;

Consider following piece of code:
JSONObject json = new JSONObject();
json.put("one", 1);
json.put("two", 2);
json.put("three", 3);
If i print the jsonobject it prints like this
{"three":"1","two":"2","one":"1"}
But i want like this.
{"one":"1","two":"2","three":"3"}
Please help. Thanks in advance.
The documentation at http://www.json.org/javadoc/org/json/JSONObject.html says:
A JSONObject is an unordered collection of name/value pairs.
In other words, properties of an object are accessed by name, not by position and the default serialized form does not guarantee any specific order.
Strict positioning comes only with arrays:
JSONArray json = new JSONArray();
json.put("1");
json.put("2");
json.put("3");
json.toString(); // results in ["1", "2", "3"]
The easiest workaround to solve your problem is to use the sortedKeys() method and by iterating the JSONObject key by key, produce the JSON string manually in what ever order necessary. Implementing a custom Comparator might help also.

Categories