I have a JSON object which I have constructed within my Java program.
JSONObject jObj = {"AAA:aaa","BBB:bbb","CCC:ccc"}
I am sending this object to a server in which it expects the JSON object in the following type.
{"BBB:bbb", "AAA:aaa", "CCC:ccc"}
My question is that does the order of the JSON object really matters on the server side? If yes, how can I change the order?
My question is that does the order of the JSON object really matters on the server side?
It should not matter. According to various JSON specifications, the order of the attributes is not significant. For example:
"An object is an unordered set of name/value pairs." (Source json.org)
"An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array." (Source RFC 7159)
Unfortunately, there are nitwits out there1 who ignore that aspect of the specs, and place some significance on the order of the attributes. (The mistake is usually made when there is a disconnect between the people specifying the APIs and those implementing them, and the people doing the specification work don't really understand JSON.)
Fortunately, the chances are that whoever designed / implemented the server didn't make that mistake. Most Java JSON parsers I've come across don't preserve the attribute order when parsing ... by default2. It would be hard to accidentally implement a server where the order of the JSON attributes being parsed was significant.
If yes, how can i change the order?
With difficulty, I fear:
You could generate the JSON by hand.
There is at least one JSON for java implementation3 that allows you to supply the Map object that holds a JSON object's attributes. If you use a LinkedHashMap or TreeMap, it should retain the insertion order or the lexical order of the attribute keys.
1 - For example, the nitwits that this poor developer was working for ... https://stackoverflow.com/a/4515863/139985
2 - RFC 7159 also says this: "JSON parsing libraries have been observed to differ as to whether or not they make the ordering of object members visible to calling software. Implementations whose behavior does not depend on member ordering will be interoperable in the sense that they will not be affected by these differences.". By my reading, this recommends that JSON libraries should hide any order of the pairs from application code.
3 - JSON-simple : https://code.google.com/p/json-simple/. There could be others too.
IMHO not possible.
JSON docs says
An object is an unordered set of name/value pairs
So the way is getting the values in required order,rather than ordering json
You could use list assuming your server can accept it:
{"list": [ {"AAA":"aaa"},{"BBB":"bbb"},{"CCC":"ccc"}]}
The other answers rightly point out that the order should not matter. There are circumstances were the order may matter in a specific implementation that misunderstands the unordered nature of JSON.
For example say you want take a hash of the JSON string and store the hash for comparison against future hashes. The hash would be different if the order of the fields in the JSON string is not the same the next time you create the hash (even thought the data in the JSON string is the same).
This can happen if you're working with an API or a deserializer that returns JSON strings, with the fields in an inconsistent order.
This question more thoroughly discusses that issue and provides solutions to getting a consistent order JSON order mixed up
The order of fields in a JSON object actually can matter. It depends on the serializer you are using. For example, when you serialize an inherited object you will get an extra JSON field called type=''. When you deserialize it the type field must come before any other JSON Field, otherwise it takes on the type of the parent.
Related
I have an external key-value storage, which contains a set of binary values per key. These binary values are Scala objects serialized using Jackson 2.5 with a ScalaPlugin.
To preserve set semantics in the storage, binary representation of an object should be stable, i.e. serializing it two times should result in the same sequence of bytes. Does Jackson have this guarantee? If it uses JSON serialization as an intermediate step for example, there is no node ordering, so binary serialization will not be stable.
This may get even more tricky if an object contains unordered structures internally (like sets or maps). Does Jackson handle that?
If not, are there sound alternatives?
Update:
I have found com.fasterxml.jackson.databind.SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS which resolves a part of the question.
You can use the option SORT_PROPERTIES_ALPHABETICALLY as mentioned in the answers of this question to achieve stable serialization (together with the option ORDER_MAP_ENTRIES_BY_KEYS that you already mentioned).
Some more background is explained in these emails:
"... in absence of explicit declaration (via #JsonPropertyOrder), and general mechanisms (sort-alphabetically; Object Id and Type Id preceding other properties), there is no defined ordering."
and
"One thing to note is that Oracle did change behavior of JDK 7, such that previously stable ordering of methods and fields returned by Introspection become arbitrary." ... "Existing default ordering is based on simple traversal and ordering that JDK provides; ...".
(copied from the email from Tatu Saloranta).
I have a JSON string representing an object, and I want to put its information into a Java object B with a different structure. Currently the solution I am taking is creating a Java Object A with a structure identical to the JSON object, made the conversion from JSON to A using Jackson and later, made the mapping from A to B using Dozer with XML mappings. Is there anyway to avoid having the A objects?
Making it short, currently I have this:
JSON--Jackson-->A--Dozer(XML mappings)-->B
and I would like to achieve this
JSON--???-->B
You may know this already, but Jackson can use loosely structure types like Map, or JsonNode as target, so you can do, say:
JsonNode root = mapper.readTree(jsonSource);
Map<String,Object> asMap = mapper.readValue(jsonSource, Map.class);
and then construct your B. Jackson has only limited amount of structural conversions (simple unwrapping), by design, although there is extensive set of scalar conversions (non-structural conversions), so if you do need structural changes it may make sense to use a library that is focused on structural changes.
I am deserialising a json object as below
{
"b":"value1",
"a":"value2",
"d":"value3",
"c":"value4",
"f":"value5",
"e":"value6"
}
But i am getting ClassCastException as below
java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.LinkedHashMap
My deserialisation code is
LinkedHashMap<String, String> map = new JSONDeserializer<LinkedHashMap<String, String>>().deserialize(JSONstring);
But when i use HashMap instead of LinkedHashMap it works but output gets sorted as below (Its not original order).
{
a=value2,
b=value1,
c=value4,
d=value3,
e=value6,
f=value5
}
I want to get the output in original order.
I found this related link
Flex JSON unable to properly serialize/deserialize LinkedHashMap
but didn't get how to use ObjectFactory.
I would appreciate any help!
Thanks in advance!
(Disclaimer: I just downloaded flexjson and debugged through its source code, so my answer might be slightly incomplete.)
In short:
You generally cannot get the entries in original order using flexjson.
Even writing a custom ObjectFactory will not work.
This is most likely intended and correct.
In detail:
First, the use of generics in new JSONDeserializer<LinkedHashMap<String,String>>() only affects the compilable code, flexjson cannot use this information to actually return a LinkedHashMap<String,String> (this is because the compiler removes the generic and the implementing class has no information of this generic type at runtime).
So, looking deeper into what happens during deserialization, it seems that during parsing the input string, the data is automatically converted to the correct type (string, date, number, list, etc.). This is done using some kind of autodetection of the required data type, because JSON does not provide type information in its data, so flexjson has a build-in list to support data types. It can also use custom mappings to assign values to object properties when proper class information is given (on serialization, flexjson adds a field class to the data to store this type information; or you can manually set this, see documentation).
But the main point is that - according to http://json.org -
An object is an unordered set of name/value pairs.
flexjson internally uses an (unordered) map to store the temporary object keys and values. Even if you tell flexjson to return the data as a LinkedHashMap the data is yet put into a HashMap before it will be converted to a LinkedHashMap, so the original order is not available at that point. (This might be fixed by replacing the map creation in flexjson.JSONTokener, line 442 with a LinkedHashMap but I didn't try that myself.)
Conclusion:
It looks like this behaviour even cannot be changed by providing a custom ObjectFactory, so as far as I understand the code, you cannot retain the original field order. (May I ask why this is important for your project?)
So, if anybody finds a solution anyway, don't hesitate to correct me.
I am using reflection to set value object properties at runtime. If everything were a string, I may not be asking this question, but that's not the case. I have a web service that returns json and I want to use the json returned by the service to populate the object. I have an ArrayList of strings called alphabeticalKeys that contains sorted keys in the json string. Here is the code I am using to dynamically populate the object (user):
for(String fieldName : alphabeticalKeys){
Log.d("JSON:" + fieldName, json.getString(fieldName));
Field f = userClass.getDeclaredField(fieldName);
f.setAccessible(true);
f.set(user, jsonObject.get(fieldName));
}
In the json data set, there are strings, doubles and more. This is part of a factory class where the type of object being returned is unknown at compile time. Also, the json fields' data types may vary depending on the type of object needed.
The json output matches the field names in the returned object, so I am looking for a way to handle the different data types returned in the json output. Can somebody offer up a suggestion?
Thx! Vivian
There are libraries available to aid in setting property values using reflection, converting to the appropriate type if necessary. For example, Spring Framework's BeanWrapper and Apache Commons BeanUtils.
There are also json libraries that will handle mapping json to/from java objects. For example, Gson and Jackson. This may make it easier, especially if the json structure closely matches the java object structure.
I am using GSON to decode JSON strings that are returned from our server. I haven't had any problems, until I ran into this one particular JSON return from the API. The return is in the following format:
"success":1,"errors":[],"data":{"524":{"id":"524"}, "525":{"id":"525"}}
For the other returns I had data as an array of a class of my own creation, but for this return it says that it is an object and not an array. So how should I format my class?
***edit: What I am having trouble with is that the '524' and '525' fields are not static names. They are dependent on what the user's credentials are. There could be fields 323, 324, 325 or a single one 123. It all depends. How would I be able to handle this dynamically?
SOLVED*
What I had to was make 'data' a <String, Object> hashmap in my custom class. Then after the first decoding, I turned 'data' into an array of type Object []. Then for each Object[i], I converted it into a JSON string. After that I used gson.fromJson() to convert it into what I had originally intended for it to be.
If the API is giving inconsistent results and you can't find a reason on your end why it is doing so, one option is to parse the object into a GSON JSONObject o = gson.fromJson(String) and then convert the data to a list if it is not one already by doing o.getElement("data").isList(), etc..
When this is complete, you can then create the object via gson.fromJson(JSONObject,Class). The alternative is to have two classes, one for each instance, but this seems sloppy if this is the only reason to have two different classes.
GSON is correct. From server reply data is object with two members that are objects also. To be array data should have square brackets [] instead of curly brackets {}. More about JSON format here.
Server format was changed or you tried another API version or someone made bug on server side.