Preserving parts of raw content during JSON and/or XML deserialisation - java

I am looking for a mechanism to deserialise a JSON representation of a map with polymorphic values out of the following string {"name": "your doubles", "values": [25.0, 15.0]} and into an instance of HashMap<String, Serializable>. As I cannot pass individual value types to the deserialiser (even though I know them) for every element of type Serializable I want to keep the original JSON string representation to deserialise it into a concrete type separately. I could use fasterxml or GSON or any other library that can do the job in a sensible manner.
I would have the same question for XML serialisation.
So for the above example I would like to generate a map, which values equal "\"your doubles\"" and "[25.0, 15.0]". Effectively, I need a custom deserializer that preserves the raw data whenever it finds a node that needs to be deserialized into a Serializable.
There is a straightforward solution to the problem, here is using Gson:
Gson gson = builder
.registerTypeAdapter(Serializable.class, new SerializableDeserializer())
.create();
private static class SerializableDeserializer implements JsonDeserializer<Serializable> {
#Override public Serializable deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return json.toString();
}
}
However, if I am not mistaken this solution actually parses the node under the Serializable and then serialises it back. So if the value is large I will end up parsing it twice.
Additionally, I failed to implement this same solution for XML using the fasterxml XML parser. The problem there is that, as mentioned above, it actually parses the node and then serialises is back, but into JSON.
Any better JSON options?
Any XML solution?

Related

How to deserialize json map of String string

I have json as below
{
"group": "Mygroup",
"name1": "aaa",
"name2": "bbb"
}
I know that we can deserialize to map. But how can we wrap it inside the object, without any custom deserializer
public class GroupInfo {
private String group
private Map<String, String> names;
}
Gson offers this kind of deserialization. You just need to define a class with the same fields as the JSON keys of the JSON being parsed.
Article on using Gson for this usage - https://dzone.com/articles/deserializing-json-java-object
Gson repo - https://github.com/google/gson
If you aren't dead set on JSON, I would recommend looking into Protocol Buffers. Protocol Buffers offer this type of functionality out of the box, are language agnostic (to a large extent anyways), and they're usually much faster than JSON.
Protocol Buffers - https://developers.google.com/protocol-buffers/docs/tutorials

Jackson crash when try to map a JSON without an element of the class

I'm having problems mapping an object using Jackson.
The issue happens when I map a JSON object that sometimes is missing an item from the class.
I'm trying to find out how to set up the configurations in order to not crash when the JSON does not have all the fields of the class.
I've already tried with:
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
#JsonIgnoreProperties(ignoreUnknown = true)
This is the error:
com.fasterxml.jackson.databind.JsonMappingException: Instantiation of [simple type, class com.non.real.package.Like] value failed: null (through reference chain: com.non.real.package.CardFeed["likes"]->com.non.real.package.CardLikes["likes"]->java.util.ArrayList[0])
"likes": {
"count": 0,
"likes": []
}
Trying different solutions I've found out that the Like object is extending the class Model of ActiveAndroid. Removing that "extension" and it works fine. I think the Model class does not work fine when it has a NULL or EMPTY.
For Jackson you could try changing the mapper's configuration directly:
mapper.setSerializationInclusion(Include.NON_NULL);
But may I suggest you look at another library to map JSON to POJO? Both GSON and Genson (my personal favorite) do the same, but much faster, and much easier. Take a look at the benchmarks here, where they compare the (de)serialization of Jackson, GSON and Genson.
With Genson, it's very easy to skip null values:
private static final Genson gensonSkipNulls = new Genson.Builder().setSkipNull(true).create();
/**
* Deserializes JSON into a Java object.
*
* #param json The JSON to deserialize.
* #param superclass The model to deserialize the JSON into.
* #return An object that is an instanceof superclass.
*/
public Object deserialize(final String json, final Class superclass) {
return genson.deserialize(json, superclass);
}

What is the most suitable Java data structure for representing JSON?

I' m developing a RESTful Android mobile client. Information exchange between my app and server is in JSON. So I' m now a little bit confused what data structure choose for represent JSON responses and data because there a lot of them. I've just stopped with LinkedHashMap<> but as far as i know JSON is unordered. Across the Internet I saw people use Map<> or HashMap<> for this. So the question - what is the best data structure for this purpose? Or if there is no a univocal answer - pros and cons of using data structures I' ve mentioned.
I would disagree with the first answer. The REST paradigm was developed so that you would operate with objects, rather than operations.
For me the most sensible approach will be if you declare beans on the client side and parse the json responses and request through them. I would recommend using the GSON library for the serialization/ deserialization. JsonObject/ JsonArray is almost never the best choice.
Maybe if you give examples of the operations you are about to use we might be able to help more precisely.
EDIT: Let me also give a few GSON Examples. Let's use this thread to compare the different libraries.
In the most cases REST services communicate objects. Let's assume you make a post of product, which has reference to shop.
{ "name": "Bread",
"price": 0.78,
"produced": "08-12-2012 14:34",
"shop": {
"name": "neighbourhood bakery"
}
}
Then if you declare the following beans:
public class Product {
private String name;
private double price;
private Date produced;
private Shop shop;
// Optional Getters and setters. GSON uses reflection, it doesn't need them
// However, better declare them so that you can access the fields
}
public class Shop {
private String name;
// Optional Getters and setters. GSON uses reflection, it doesn't need them
// However, better declare them so that you can access the fields
}
You can deserialize the json using:
String jsonString; // initialized as you can
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("MM-dd-yyyy HH:mm"); // setting custom date format
Gson gson = gsonBuilder.create();
Product product = gson.fromJson(jsonString, Product.class);
// Do whatever you want with the object it has its fields loaded from the json
On the other hand you can serialize to json even more easily:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("MM-dd-yyyy HH:mm"); // setting custom date format
Gson gson = gsonBuilder.create();
String jsonString = gson.toJson(product);
Are you talking about receiving and parsing the JSON string from a server request?
For that you can use:
import org.json.JSONArray;
import org.json.JSONObject;
Using these, I read through my JSON array from my POST request and store the resulting information in Class objects in my project.
For each item in JSONArray, you can extract the JSONObject and attributes like this:
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
jsonObject.getString("text");
}
As far as actually storing the data, like mentioned above, JSON data can come in a wide array of formats depending on the source, and as such, it is usually parsed on the client end and saved in your application Class objects for use. Or more generically, you could store the data using Map<String, Object>
This is easily the best answer I've seen:
https://dzone.com/articles/which-is-the-right-java-abstraction-for-json
Summary: there are three abstrations: pojos, maps and lists, and custom classes to represent objects, arrays, and primitives. There are advantages and disadvantages to each, with no clear winner.
Pojos have the biggest advantages, but you can't always use them. Use them if you can, and use the others if you must.
If you are doing anything other than the most simple mapping then you should use a full class structure. Create your class hierarchy as a mirror of the data structure in JSON and use Jackson to map the JSON directly to the class hierarchy using the ObjectMapper.
With this solution you don't have any casting of Object to Map or messing around with JSONObject or JSONArray and you don't have any multi-level map traversal in your code. You simply take the JSON string, feed it to the ObjectMapper, and get a your Object, which contains child objects (even collections) automatically mapped by the ObjectMapper.
I've used xstream to serialize JSON, in the following way:
XStream xstream = new XStream(new JsonHierarchicalStreamDriver());
xstream.setMode(XStream.NO_REFERENCES);
xstream.alias("myAlias", MyClass.class); // requires a no argument constructor
System.out.println(xstream.toXML(product));
Ok, the gentleman in the comments wants a deserialization example, here you are:
XStream xstream = new XStream(new JsonHierarchicalStreamDriver());
xstream.alias("myAlias", MyClass.class);
Product product = (Product)xstream.fromXML(json);
System.out.println(product.getName());
Let me know if you need further assistance...

JSON Polymorphism

I have a List of javascript objects on my client side, which are a list of "events" that a user has executed. When the user is ready, I want to send this to the server. The order of events is important, so preserving the list order is necessary.
What I would like to do is to have a JSON library (don't mind which one) to bind the JSON to some Event objects in my Java code, where Event is an abstract class, and I have 3 concrete classes that all extend Event (lets say EventA, EventB and EventC).
Ideal scenario would be something like
List<Event> events = jsonlibrary.deserialise(jsonString);
which may contain a list of items such as
[eventA, eventC, eventA, eventA, eventB]
Is this possible, or do I have to inspect the JSON tree manually, and deserialise the individual elements of the json array?
JSON objects are just key/value pairs and contain no type information. That means identifying the type of a JSON object automatically isn't possible. You have to implement some logic on the server-side to find out what kind of event you are dealing with.
I would suggest to use a factory method which takes a json string, parses it to find out what kind of Event it is, builds an Event object of the correct subclass and returns it.
You could use Genson library http://code.google.com/p/genson/.
It can deserialize to concrete types if the json was produced using Genson. Otherwise you only need to add something like [{"#class":"my.java.class", "the rest of the properties"}...]
// an example
abstract class Event {
String id;
}
class Click extends Event {
double x, y;
}
// you can define aliases instead of plain class name with package (its a bit nicer and more secure)
Genson genson = new Genson.Builder().setWithClassMetadata(true).addAlias("click",
Click.class).create();
String json = "[{\"#class\":\"click\", \"id\":\"here\", \"x\":1,\"y\":2}]";
// deserialize to an unknown type with a cast warning
List<Event> events = genson.deserialize(json, List.class);
// or better define to which generic type
GenericType<List<Event>> eventListType = new GenericType<List<Event>>() {};
events = genson.deserialize(json, eventListType);
EDIT
here is the wiki example http://code.google.com/p/genson/wiki/GettingStarted#Interface/Abstract_classes_support
Why not using jackson json library ?
It is a full Object/JSON Mapper with data binding functionnality.
It is fast, small footprint, documented, overused, and many others things you will enjoy!
I began a library that implements the desired fonctionality (for json and xml) if the json is encoded by the same library :
https://github.com/giraudsa/serialisation
to use it,
MyObject myObject = new SpecialisedObject();
String json = JsonMarshaller.ToJson(myObject);
MyObject myClonedObject = JsonUnMarshaller(json);

How to convert JAVA Object to JSON Efficiently..?

I am using Mule. I have a JAVA Object that is populated from my internal Class..It is actually a HashMap<String,Object>. Object can be anything..another HashMap, OR List etc ..Now i have to convert it into JSON (and removing all those keys that have value as NULL)..
When i use a given Mule Transformer , ObjectToJSON, it is converting into appropriate JSON..but not able to remove NULL value..And i could not find any properties to set in Custom-transformer that will remove NULL values..!!
So then, i wrote a custom transformer, that uses the net.sf.json-lib library and i am able to remove NULL values.
But in one of my JAVA Object , i have a HashMap<Integer,String> and since in JSON Object , Integer cannot be keys, net.sf.json library is giving an Exception :
Exception stack is:
1. JSON keys must be strings. (java.lang.ClassCastException)
net.sf.json.JSONObject:1120 (null)
2. java.lang.ClassCastException: JSON keys must be strings. (net.sf.json.JSONException)
net.sf.json.JSONObject:1160 (null)
3. java.lang.ClassCastException: JSON keys must be strings. (net.sf.json.JSONException). Message payload is of type: HashMap (org.mule.api.transformer.TransformerMessagingException)
and so it is unable to convert it into JSON..
So what is most viable option..??
I would recommend you to try gson it worked like a magic for me.
Collections Examples
Gson gson = new Gson();
Collection<Integer> ints = Lists.immutableList(1,2,3,4,5);
(Serialization)
String json = gson.toJson(ints); ==> json is [1,2,3,4,5]
(Deserialization)
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);
ints2 is same as ints
Here is an example of how to write a custom serializer for JodaTime DateTime class.
private class DateTimeSerializer implements JsonSerializer<DateTime> {
public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toString());
}
}
Have you looked at Gson?
http://sites.google.com/site/gson/gson-user-guide#TOC-Null-Object-Support
From http://www.ietf.org/rfc/rfc4627.txt
An object structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members). A name is a string.
I would suggest to modify your initial Java structure to use String as key type.
However with Jackson library you can create fancier solutions:
Use a custom deserializer Deserializing non-string map keys with Jackson
Use a Tree Model instead of your own Java POJO http://wiki.fasterxml.com/JacksonInFiveMinutes

Categories

Resources