During a recent job interview, i was asked the steps taken to convert Java object to JSON using Jackson.
Although, I havent done it before, I have seen examples where Jackson was used and by using object mapper the java object is converted to JSON.
However, the interviewer asked "how and where is the JSON schema set up"
I thought this was done automatically. Does one have to specify how the JSON has to be returned?
I have seen examples where the toString is overriden - is that where the schema is specified.
Thanks
I think the interviewer doesn't mean to ask you how to use Jackson, but how JSON is constructed from a Java Object.
Here's what I thought:
Jackson will detect every field's name as keys;
Iterate the keys to get their values and put it into the JSON.
If a field has child object, it will do step 1 and 2 recursively.
Note: The Java class should implementation the serialization interface.
Related
I'm parsing json with Gson but I'm struggling with the data I'm getting. This is part of an API out of my control (openFDA) so changing that might not be an option.
Here's the json I'm strugling with: https://api.fda.gov/device/event.json?search=device.generic_name:generator&limit=10
There are some fields that are not consistent, for example remedial_action. Sometimes it comes out like this:
"remedial_action": [
"Recall"
]
and in other results like this:
"remedial_action": ""
So it's either an array or a plain string. Is there a way to handle this? If not possible in Gson, any other json parsing library that can help?
I created my pojos here in case someone needs the code. There are a few files created from that and didn't want to spam them here. I can add them if needed.
Update: The bug has been confirmed and it's scheduled for a fix.
It is possible through GSON, by using a TypeAdapter.
Here are the initial steps I would use to do that:
Create a POJO that contains the array and the String. Let's call it RemedialAction.
In your original POJO, create an attribute of the new class.
Create a class that extends TypeAdapter<RemedialAction>.
Override the read() and write() methods and create the logic in them.
That should be a little hard to parse, though. Read this tutorial for more information.
Note: you can customize getRemedialAction() to give you only the valid return -- array or String.
I have a nested data structure, where somewhere down the hierarchy the same objects are used several times. What I want as a result is, that when serializing this via Jackson, it is somehow detected than an object has already been written to the output and instead of serializing the object again, its ID is used.
Is Jackson able to do this for me, or do I have to implement this manually?
Example:
AddressBook
|
Person
|
Tag
A lot of Persons can have the same Tag. I only want each Tag object once in the JSON output.
It seems pretty trivial to implement manually - just have a HashSet containing all the Tag objects. Then, as you're serializing, if an object's tag is already contained in the set, you know it's already been serialized.
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 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.
I am using Axis to call a SOAP-based web service. I'm then trying to serialize the returned remote object as JSON, using the Google Gson library.
The serialization to JSON fails, with Gson complaining that "there are multiple elements with the name __equalsCalc()).
When I inspect the returned object in my IDE (Eclipse), I can see that this is true -- the returned object has three members called __equalsCalc() and another three called __hashCode.
I know from looking around that these are added by WSDL2Java (I think) in order to avoid recursion. My question is, why are there THREE of each? And how can I get the serializer to ignore these? They're not actually part of the object's definition (it's called a RemoteProject, for reference). Can I do something hackish like cast the RemoteProject to a RemoteProject to get it to drop those members?
This turns out to be not too hard to solve. I have multiple copies of the same instance var because the class being serialized is shadowing fields of the same name from superclasses. Since I don't care about these fields, the best approach in Gson is to write a custom ExckusionStrategy which can selectively ignore fields based on their name:
http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/ExclusionStrategy.html
I don't know GSon.
With Jackson, you can annotate properties (i.e - fields that have getters/setters according to Java bean convention) with #JsonIgnore.
This way you can prevent issues like recursion/no matching setter or getter and so on...
Try to find out if you have the same at GSon or use Jackson.