Performance penalty using intermediate model (Map) for Jackson/GSON serialising - json

I have a project where I need to support serialising model classes to JSON using both Jackson and GSON (switchable).
Besides simply converting these model classes to JSON I also need to manipulate the by adding/removed certain keys (as per user input).
I was thinking of converting my model classes (and the logic to remove/add data) to simple java.util.Maps and convert these to JSON. Which works.
To convert these model classes to the java.util.Maps for Jackson I'm doing:
Map<String, Object> jsonMap =
mapper.convertValue(object, new TypeReference<Map<String, Object>() {})
and for GSON:
JsonElement jsonElement = gson.toJsonTree(object);
Map<String, Object> jsonMap =
gson.fromJson(jsonElement, new TypeToken<Map<String, Object>>(){}.getType());
After manipulating the data in the map, I do the following to actually serialize the map to JSON string:
// Jackson
mapper.writeValueAsString(jsonMap);
// GSON
gson.toJson(jsonMap);
Is there a performance hit to convert a model Object to a Map instead of a Jackson JsonNode (mapper.convertValue(object, ..) vs. mapper.valueToTree(object))?
Would it be possible to directly convert a model Object to a Map using GSON? Now I'm first creating a JsonElement and then converting it to a Map.

Jackson's ObjectNode uses LinkedHashMap internally (and ArrayNode uses ArrayList), so there should not be much difference between these approaches. JsonNode model can optimize some things slightly better than "raw" Lists and Maps; but on the other hand there is thin wrapper that adds some memory usage... so in the end things probably even out.

Related

Flutter - What is the best way to parse Json?

Actually, I am using the traditional way to work with Json:
factory MyObject.fromJson(Map<String, dynamic> json)
I have a lot of objects dealing with Json and over time, I encounter problems like:
Converting object to an encodable object failed: Instance of 'MyObject'#0
I am looking for the best way (external plugin or something else) to manipulate these Json.
Take a look on json_serializable package.
And docs has an excellent resource about JSON serialization.
This is how I would set up the MyObject class to parse Json
class MyObject {
String value;
MyObject({this.value});
static MyObject fromMap(Map<String,dynamic> map){
var value = map['value'];
return MyObject(value:value);
}
}

ExtJS - convert json to Model

I have a json string that I need to map into a Model, I've been checking this json reader, Ext.data.reader.JsonView, but it seems that it only wokrs with a proxy, I need to pass a string (which contains the json) and map it to my model. Is that possible?
Thanks,
Angelo.
Take a look on the Ext.data.model's constructor.
http://docs.sencha.com/extjs/4.2.3/#!/api/Ext.data.Model-method-constructor
You can pass your data into it and it will map it to your model's fields. So you can do something like:
var model = new Ext.data.model(Ext.decode(<yourJsonString>));
Ext.data.model can be replaced with your model class.

JSONObject Alternative in Spring and Jackson

I need to pass a map back to the web application.
I'm used to encapsulating the map in a JSONObject
http://json.org/java/
But since I am using Spring and Jackson Haus.
is there an easier way to maintain the pojo? May I can just annotate the MAP ?
Jackson has com.fasterxml.jackson.core.JsonNode, and specific subtypes like ObjectNode.
These form so-called Tree Model, which is one of 3 ways to handle JSON with Jackson -- some other libraries (like org.json) only offer this way.
So you should be able to just use JsonNode instead; there is little point in using org.json library; it is slow, and has outdated API.
Alternatively you can just use java.util.Map, and return that. Jackson can handle standard Lists, Maps and other JDK types just fine.
If you need to manipulate the output, ie, you don't want to provide all the fields of the object you can use JSonArray:
#RequestMapping(value = "/api/users", method = RequestMethod.GET)
public
#ResponseBody
String listUsersJson(ModelMap model) throws JSONException {
JSONArray userArray = new JSONArray();
for (User user : userRepository.findAll()) {
JSONObject userJSON = new JSONObject();
userJSON.put("id", user.getId());
userJSON.put("firstName", user.getFirstName());
userJSON.put("lastName", user.getLastName());
userJSON.put("email", user.getEmail());
userArray.put(userJSON);
}
return userArray.toString();
}
Use the example from here
Otherwise if you add jackson to your dependencies and set the controller method anotatted with #ResponseBody the response will automatically mapped to JSON. Check here for a simple example.

force jackson mapper to always add class type on writeValue without annotations

Is it possible to configure jackson to always add the type of the serialized object to the generated json output.
For example:
package org.acme;
class ClassA
{
String a;
String b;
}
and I want the generated json to be:
["org.acme.ClassA",{"a":"str1","b":"str2"}]
You can do that with enableDefaultTyping() of the ObjectMapper
e.g.
mapper.enableDefaultTyping(DefaultTyping.OBJECT_AND_NON_CONCRETE);
See ObjectMapper API
If your are free to change from Jackson and do not especially need the format to match the one your are showing you can try Genson http://code.google.com/p/genson.
For example if your requirement is to be able to deserialize interfaces or abstract classes based on the original type of the object you serialized you can do:
interface Entity {}
static class Person implements Entity {}
Genson genson = new Genson.Builder().setWithClassMetadata(true).create();
// json will be equal to {"#class":"my.package.Person"}
String json = genson.serialize(new Person());
// and now Genson is able to deserialize it back to Person using the information
// in the Json Object
Person person = (Person) genson.deserialize(json, Entity.class);
Another nice feature is the ability to define aliases for your classes, so you show less information in the json stream but also this allows you to do refactoring without worring of existing json streams (for example if you store it in a database).
Genson genson = new Genson.Builder().addAlias("person", Person.class).create();
// json value is {"#class": "person"}
String json = genson.serialize(new Person());
Have a look at the wiki.

Jackson: is there a way to serialize POJOs directly to treemodel?

I'm looking for a way to directly convert some POJO to a Jackson TreeModel. I know that a translation from POJO-to-JSON-String exists, and TreeModel-to-JSON-String is supported — hovewer I am looking for a POJO-to-TreeModel translation. Is there a way?
The use-case is as follows:
Server-side templating is done with the Java implementation of Mustache. This uses Jackson's TreeModel.
After that, I need a slimmed-down version of the TreeModel on the client-side, so I want to be able to first filter the TreeModel, serialize that to JSON, then send it to the client-side for further processing.
This, ideally, involves two serialization steps. However, in my workaround, I am currently using three — which you can see here:
map = // a map of pojos with jackson annotations
//pojo >> JSON
StringWriter w = new StringWriter();
objectmapper.writeValue(new JsonFactory().createJsonGenerator(w), map);
String json = w.toString();
w.close();
//JSON >> Treemodel
JsonNode tree = GenericJcrDTO.mapper.readTree(json);
//filter tree here
//treemodel >>JSON
StringWriter w = new StringWriter();
GenericJcrDTO.mapper.writeValue(new JsonFactory().createJsonGenerator(w), tree);
json = w.toString();
w.close();
Anyone?
To answer my own question:
JsonNode node = objectMapper.valueToTree(map);