Jackson VS. Gson

Jackson Vs. Gson

I did this research the last week and I ended up with the same 2 libraries. As I'm using Spring 3 (that adopts Jackson in its default Json view 'JacksonJsonView') it was more natural for me to do the same. The 2 lib are pretty much the same... at the end they simply map to a json file! :)

Anyway as you said Jackson has a + in performance and that's very important for me. The project is also quite active as you can see from their web page and that's a very good sign as well.

Jackson vs Gson for simple deserialisation

With Jackson 1.4+ you can use the class-level @JsonIgnoreProperties annotation to silently ignore unknown fields, with ignoreUnknown set to true.

@JsonIgnoreProperties(ignoreUnknown = true)
public class TwitterUser {
// snip...
}
  • http://wiki.fasterxml.com/JacksonAnnotations
  • http://wiki.fasterxml.com/JacksonHowToIgnoreUnknown

Jsonpath with Jackson or Gson

The Jayway JsonPath library has support for reading values using a JSON path.

For example:

String json = "...";

Map<String, Object> book = JsonPath.read(json, "$.store.book[0]");
System.out.println(book); // prints {category=reference, author=Nigel Rees, title=Sayings of the Century, price=8.95}

Double price = JsonPath.read(json, "$.store.bicycle.price");
System.out.println(price); // prints 19.95

You can also map JSON objects directly to classes, like in GSON or Jackson:

Book book = JsonPath.parse(json).read("$.store.book[0]", Book.class);
System.out.println(book); // prints Book{category='reference', author='Nigel Rees', title='Sayings of the Century', price=8.95}

If you would like to specifically use GSON or Jackson to do the deserialization (the default is to use json-smart), you can also configure this:

Configuration.setDefaults(new Configuration.Defaults() {
private final JsonProvider jsonProvider = new JacksonJsonProvider();
private final MappingProvider mappingProvider = new JacksonMappingProvider();

@Override
public JsonProvider jsonProvider() {
return jsonProvider;
}

@Override
public MappingProvider mappingProvider() {
return mappingProvider;
}

@Override
public Set<Option> options() {
return EnumSet.noneOf(Option.class);
}
});

See the documentation for more details.

Converting byte[] to json and vice versa without jackson or gson

If it would be so easy, then Jackson or Gson was never be born.

I am affraid, that you have to declared deserializer for all of your objects manualy. This is not a rocket science, but it takes time to do it. This is an example:

public static void main(String[] args) {
Data data = new Data(11, 12);
String json = toJson(data);
System.out.println(json);

byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
Data res = toDataObj(bytes);
System.out.println(res.a);
System.out.println(res.b);
}

public static String toJson(Data data) {
JSONObject jsonObj = new JSONObject();
jsonObj.put("a", data.a);
jsonObj.put("b", data.b);
return jsonObj.toString();
}

public static Data toDataObj(byte[] bytesClass) {
JSONObject jsonObject = new JSONObject(new String(bytesClass, StandardCharsets.UTF_8));
Data data = new Data(0, 0);
data.a = jsonObject.getInt("a");
data.b = jsonObject.getInt("b");
return data;
}

public static class Data {

int a;
int b;

public Data(int a, int b) {
this.a = a;
this.b = b;
}
}

Here you can get more info:

  • How to create JSON Object using String?
  • How to parse JSON in Java

Json parsing using jackson or Gson

please add object for global object

Class ResultJson{
String last_sync_dt;
ArrayList<MeetingInfo> meetings_info;
}

and MeetingInfo will be

public class MeetingInfo {
private String date;
private String meeting_id;
private String subject;
private CustomerInfo customerInfo;

public void setDate(String date) {
this.date = date;
}

public void setMeeting_id(String meeting_id) {
this.meeting_id = meeting_id;
}

public void setSubject(String subject) {
this.subject = subject;
}

public void setCustomer(CustomerInfo customer) {
customerInfo = customer;
}
}

Customer info class

public class CustomerInfo {
private String customer_id;
private String customer_name;

public void setCustomerId(String customer_id) {
this.customer_id = customer_id;
}

public void setCustomerName(String customer_name) {
this.customer_name = customer_name;
}
}

Meeting deserializer

public class MeetingInfoAutho implements JsonDeserializer<MeetingInfo>{

@Override
public MeetingInfo deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject jObject = jsonElement.getAsJsonObject();
MeetingInfo info = new MeetingInfo();
CustomerInfo customer = new CustomerInfo();
customer.setCustomerId(jObject.get("customer_id").getAsString());
customer.setCustomerName(jObject.get("customer_name").getAsString());
info.setDate(jObject.get("date").getAsString());
info.setMeeting_id(jObject.get("meeting_id").getAsString());
info.setSubject(jObject.get("subject").getAsString());
info.setCustomer(customer);
Log.e("info", jObject.toString());
return info;
}
}

and final call to json string to object

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MeetingInfo.class, new MeetingInfoAutho());
Gson gson = gsonBuilder.create();
ResultJson resultObject = gson.fromJson(jsonStr, ResultJson.class);

You should create MeetingInfoAutho which implements JsonDeserializer. Please find some examples about JsonDeserializer GSON for more info.
This will give exact result.

How to compare JSON documents and return the differences with Jackson or Gson?

Reading the JSON documents as Maps and comparing them

You could read both JSON documents as Map<K, V>. See the below examples for Jackson and Gson:

ObjectMapper mapper = new ObjectMapper();
TypeReference<HashMap<String, Object>> type =
new TypeReference<HashMap<String, Object>>() {};

Map<String, Object> leftMap = mapper.readValue(leftJson, type);
Map<String, Object> rightMap = mapper.readValue(rightJson, type);
Gson gson = new Gson();
Type type = new TypeToken<Map<String, Object>>(){}.getType();

Map<String, Object> leftMap = gson.fromJson(leftJson, type);
Map<String, Object> rightMap = gson.fromJson(rightJson, type);

Then use Guava's Maps.difference(Map<K, V>, Map<K, V>) to compare them. It returns a MapDifference<K, V> instance:

MapDifference<String, Object> difference = Maps.difference(leftMap, rightMap);

If you are not happy with the result, you can consider flattening the maps and then compare them. It will provide better comparison results especially for nested objects and arrays.

Creating flat Maps for the comparison

To flat the map, you can use:

public final class FlatMapUtil {

private FlatMapUtil() {
throw new AssertionError("No instances for you!");
}

public static Map<String, Object> flatten(Map<String, Object> map) {
return map.entrySet().stream()
.flatMap(FlatMapUtil::flatten)
.collect(LinkedHashMap::new, (m, e) -> m.put("/" + e.getKey(), e.getValue()), LinkedHashMap::putAll);
}

private static Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entry) {

if (entry == null) {
return Stream.empty();
}

if (entry.getValue() instanceof Map<?, ?>) {
return ((Map<?, ?>) entry.getValue()).entrySet().stream()
.flatMap(e -> flatten(new AbstractMap.SimpleEntry<>(entry.getKey() + "/" + e.getKey(), e.getValue())));
}

if (entry.getValue() instanceof List<?>) {
List<?> list = (List<?>) entry.getValue();
return IntStream.range(0, list.size())
.mapToObj(i -> new AbstractMap.SimpleEntry<String, Object>(entry.getKey() + "/" + i, list.get(i)))
.flatMap(FlatMapUtil::flatten);
}

return Stream.of(entry);
}
}

It uses the JSON Pointer notation defined in the RFC 6901 for the keys, so you can easily locate the values.

Example

Consider the following JSON documents:

{
"name": {
"first": "John",
"last": "Doe"
},
"address": null,
"birthday": "1980-01-01",
"company": "Acme",
"occupation": "Software engineer",
"phones": [
{
"number": "000000000",
"type": "home"
},
{
"number": "999999999",
"type": "mobile"
}
]
}
{
"name": {
"first": "Jane",
"last": "Doe",
"nickname": "Jenny"
},
"birthday": "1990-01-01",
"occupation": null,
"phones": [
{
"number": "111111111",
"type": "mobile"
}
],
"favorite": true,
"groups": [
"close-friends",
"gym"
]
}

And the following code to compare them and show the differences:

Map<String, Object> leftFlatMap = FlatMapUtil.flatten(leftMap);
Map<String, Object> rightFlatMap = FlatMapUtil.flatten(rightMap);

MapDifference<String, Object> difference = Maps.difference(leftFlatMap, rightFlatMap);

System.out.println("Entries only on the left\n--------------------------");
difference.entriesOnlyOnLeft()
.forEach((key, value) -> System.out.println(key + ": " + value));

System.out.println("\n\nEntries only on the right\n--------------------------");
difference.entriesOnlyOnRight()
.forEach((key, value) -> System.out.println(key + ": " + value));

System.out.println("\n\nEntries differing\n--------------------------");
difference.entriesDiffering()
.forEach((key, value) -> System.out.println(key + ": " + value));

It will produce the following output:

Entries only on the left
--------------------------
/address: null
/phones/1/number: 999999999
/phones/1/type: mobile
/company: Acme

Entries only on the right
--------------------------
/name/nickname: Jenny
/groups/0: close-friends
/groups/1: gym
/favorite: true

Entries differing
--------------------------
/birthday: (1980-01-01, 1990-01-01)
/occupation: (Software engineer, null)
/name/first: (John, Jane)
/phones/0/number: (000000000, 111111111)
/phones/0/type: (home, mobile)


Related Topics



Leave a reply



Submit