I've been using JSON (JavaScript Object Notation) for a couple years now, but never worried about finding the best library around for the task. At the first time I needed JSON, it was for a JAX-RS web service to communicate with Android applications. So I just used Gson because it was SO easy and worked with just 1 jar on both JavaEE server and the Android app. Anyway, as I'm studying for OCEJEE6WSD, and seeing a lots of XML and JSON, I decided to test some popular libraries.

The Test

The libraries JSON.org, Jackson (with JAX-B annotations), XStream and Gson (google-gson) were tested bearing in mind how easy it is to use them to serialize an entity and how easy (and light) it is to install/bundle them in your app. The test is very simple and does not analises all functionalities the libraries provide. Fastjson was not considered because it's documentation/wiki was currently offline.

All code developed for this comparison is available in a GitHub project here: https://github.com/danielgimenes/JSONLibsComparison

The Test Case

I wanted the test to be basic, but still have some real-world app details. So the test is composed of serializing the following entity while formatting the Date and BigDecimal fields using the patterns described above. Also, to add some difficulty :) I've determined that the order of fields on the output would have to be fixed . As JSON.org library does not allow field ordering, I've used it's output as reference for the others.

[code language="java"]
public class Sales {
private List sales;
}

public class Sale {
private Integer id;
private String title;
private String productName;
private BigDecimal price; // pattern "U$ 0.00"
private Date deadline; // pattern "dd/MM/yyyy"
}
[/code]

Expected output sample:

[code]
{
"sales":[
{
"id":1,
"title":"Prepare for SCJP! Super discount on Java book 'SCJP Sun Certified Programmer for Java 6 Exam 310-065'",
"price":"U$ 25,20",
"deadline":"15/04/2014",
"productName":"SCJP Sun Certified Programmer for Java 6 Exam 310-065"
},
{
"id":2,
"title":"Be a better programmer! 'The Clean Coder' book for half the price!",
"price":"U$ 15,50",
"deadline":"05/04/2014",
"productName":"The Clean Coder: A Code of Conduct for Professional Programmers"
},
{
"id":3,
"title":"Now you can learn Test Driven Development! 'Test Driven Development: By Example' book with 25% off!",
"price":"U$ 30,00",
"deadline":"30/04/2014",
"productName":"Test Driven Development: By Example"
}
]
}
[/code]

JSON.org

The json.org website provides implementations of serializer/deserializers in several languages. The java implementation is also provided through Maven in a single 45.9kb, which is nice. The version used was "20140107". The main classes are JSONObject and JSONArray. Both provide automatic serialization of entities on constructors, but there is no way to specify formatters or any type of class that can perform formatting. Also, there is no way to force ordering of fields.

[code language="java"]
JSONObject jsonObj = new JSONObject();
JSONArray jsonArray = new JSONArray();
jsonObj.put("sales", jsonArray);
for (Sale sale : sales.getSales()) {
JSONObject jsonSaleObj = new JSONObject();
jsonSaleObj.put("id", sale.getId());
jsonSaleObj.put("title", sale.getTitle());
jsonSaleObj.put("productName", sale.getProductName());
jsonSaleObj.put("price", new DecimalFormat("U$ 0.00").format(sale.getPrice()));
jsonSaleObj.put("deadline", new SimpleDateFormat("dd/MM/yyyy").format(sale.getDeadline()));
jsonArray.put(jsonSaleObj);
}
return jsonObj.toString();
[/code]

Download: http://mvnrepository.com/artifact/org.json/json
Documentation: http://www.json.org/java/index.html

Jackson (with JAX-B annotations)

Jackson is, probably, the most famous JSON library around. It is very robust and well made and provides 3 methods for processing JSON (streaming API, tree model and data binding with annotations). As I wanted to use JAX-B annotations (to have the bonus XML serialization), this test only uses data binding method with the module JacksonJAXBAnnotations. One disadvantage of Jackson is that, to use it this way, we need 4 jars (jackson-annotations, jackson-core, jackson-databinding and jackson-module-jaxb-annotations) which totals 1.1Mb. The tested version was 2.2.3 (lib) and 2.3.0 (JAX-B module).

Annotated entities:

[code language="java"]
@XmlRootElement(name = "sales")
public class SalesJAXB {
private List sales;
}

@XmlRootElement(name = "sale")
@XmlType(propOrder = { "id", "title", "price", "deadline", "productName" })
public class SaleJAXB {
private Integer id;
private String title;
private String productName;
private BigDecimal price; // pattern "U$ 0.00"
private Date deadline; // pattern "dd/MM/yyyy"

@XmlAttribute(required = true)
public Integer getId() {
return id;
}

@XmlElement(required = true)
public String getTitle() {
return title;
}

@XmlElement(required = true)
public String getProductName() {
return productName;
}

@XmlElement(required = true)
@XmlJavaTypeAdapter(JAXBBigDecimalAdapter.class)
public BigDecimal getPrice() {
return price;
}

@XmlAttribute(required = true)
@XmlJavaTypeAdapter(JAXBDateAdapter.class)
public Date getDeadline() {
return deadline;
}
[/code]

Adapters (to format data):

[code language="java"]
public class JAXBBigDecimalAdapter extends XmlAdapter<String, BigDecimal> {
private DecimalFormat formatter = new DecimalFormat("U$ 0.00");

@Override
public BigDecimal unmarshal(String formattedDecimal) throws Exception {
return new BigDecimal(formatter.parse(formattedDecimal).doubleValue());
}

@Override
public String marshal(BigDecimal decimal) throws Exception {
return formatter.format(decimal);
}
}

public class JAXBDateAdapter extends XmlAdapter<String, Date>{
private SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");

@Override
public Date unmarshal(String formattedDate) throws Exception {
return formatter.parse(formattedDate);
}

@Override
public String marshal(Date date) throws Exception {
return formatter.format(date);
}
}
[/code]

Serialization:

[code language="java"]
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectMapper mapper = new ObjectMapper();
@SuppressWarnings("deprecation")
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
// enables "JAXB annotations only" mode
mapper.setAnnotationIntrospector(introspector);
mapper.writeValue(outputStream, salesAnnotatedWithJAXB);
return outputStream.toString();
[/code]

Download: http://wiki.fasterxml.com/JacksonDownload
Download (JAX-B module): https://github.com/FasterXML/jackson-module-jaxb-annotations
Documentation: http://wiki.fasterxml.com/JacksonDocumentation

XStream

XStream is a library for XML serialization which works with "drivers". By default, it is provided with 2 specific drivers that provide JSON serialization as well. The tested version was 1.4.5, which comes in 1 jar with 509kb. To apply Date and BigDecimal formatting, have field ordering and omit the sales list name, I had no other option but creating a custom Converter for Sales entity.

Annotated entities:

[code language="java"]
public class SalesXStream {
private List sales;
}

@XStreamConverter(SaleXStreamConverter.class)
public class SaleXStream {
private Integer id;
private String title;
private String productName;
private BigDecimal price; // pattern "U$ 0.00"
private Date deadline; // pattern "dd/MM/yyyy"
}
[/code]

Custom Converter:

[code language="java"]
public class SaleXStreamConverter implements Converter {
@Override
public boolean canConvert(@SuppressWarnings("rawtypes") Class clazz) {
return (clazz.getName().equals(SaleXStream.class.getName()));
}

@Override
public Object unmarshal(HierarchicalStreamReader arg0, UnmarshallingContext arg1) {
// we're not going to use this
return null;
}

@Override
public void marshal(Object obj, HierarchicalStreamWriter genericWriter, MarshallingContext context) {
PathTrackingWriter writer = (PathTrackingWriter) genericWriter;
SaleXStream sale = (SaleXStream) obj;
writer.startNode("id", Integer.class);
writer.setValue(sale.getId().toString());
writer.endNode();
writer.startNode("title");
writer.setValue(sale.getTitle());
writer.endNode();
writer.startNode("price");
writer.setValue(new DecimalFormat("U$ 0.00").format(sale.getPrice()));
writer.endNode();
writer.startNode("deadline");
writer.setValue(new SimpleDateFormat("dd/MM/yyyy").format(sale.getDeadline()));
writer.endNode();
writer.startNode("productName");
writer.setValue(sale.getProductName());
writer.endNode();
}
}
[/code]

Serialization:

[code language="java"]
XStream xstream = new XStream(new JsonHierarchicalStreamDriver());
xstream.processAnnotations(SalesXStream.class);
xstream.alias("sales", List.class);
return xstream.toXML(salesAnnotatedWithXStream.getSales());
[/code]

Download: http://xstream.codehaus.org/download.html
Documentation: http://xstream.codehaus.org/

Gson

Gson is Google's library for JSON object serialization. It's very easy to use, specially because of the robust toJson() and fromJson() methods. What I liked most of this library is that you can extend it just exactly what you need (e.g. only serialize X without needing to implement deserialization of X). Another advantage is the configuration of a builder, with all adapters and formating details, which then can be used on all points of the program to create Gson objects that do the actual serialization. The tested version was 2.2.4, which works with only 1 jar of 190kb.

[code language="java"]
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.disableHtmlEscaping();
gsonBuilder.setDateFormat("dd/MM/yyyy");
gsonBuilder.registerTypeAdapter(BigDecimal.class, new JsonSerializer() {
@Override
public JsonElement serialize(BigDecimal decimal, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(new DecimalFormat("U$ 0.00").format(decimal));
}
});
Gson gson = gsonBuilder.create();
return gson.toJson(sales);
[/code]

Download: https://code.google.com/p/google-gson/downloads/list
Documentation: https://sites.google.com/site/gson/gson-user-guide

My veredict

I think JSON.org library is nice, but Gson is better in every way (extending, documentation, etc). XStream is confusing, and I had difficulties in controlling exactly which objects/arrays I wanted named (or ommitted) and which driver to use. I think Gson and Jackson (with JAX-B) are both great, and their differences incentives me to use them in different situations.

If you need something simple to implement, and specially if you are implementing both ends or specifying the JSON format, use Gson. It's very well documented, easy to extend (TypeAdapters can be implemented quickly and allows you to code just what you need) and small (190kb in 1 jar). Also I loved that it already has an easy way to do Date formatting by just specifying a string pattern.

If you need more flexibility, or you're going to use serialization in several classes, or you need XML serialization as well, go for Jackson with JAX-B module. Their annotations are part of a Java standard (JSR-222), the library is very flexible (specially because of Converters, Field Ordering, etc), and you get XML and JSON in one implementation. Also, when using Java EE, some application servers like Glassfish provides out of the box XML and JSON serialization with JAX-B - so you can stick with the same technology for Java EE and Java SE (or Android) while using the best of your application server.