Some insights into JSON parsers in Java

  • 2020-04-01 02:37:23
  • OfStack

Recently, I have been studying JSON. There are many class libraries in Java that deal with JSON, lib-json, sf-json, fastjson, and Jackson JSON. Never mind the first one, performance and functionality are nothing to write home about.


The biggest advantage of sf-json is that it is easy to read randomly. The code is simple:

JSONObject json = JSONObject. FromObject (STR);

Then read the field contents:

Json.getstring or getInt or something. But productivity is questionable and error prone.

Another advantage of sf-json is that it automatically USES unicode encoding. When Chinese or symbols appear in the content, it will be automatically converted to unicode encoding like \uFFFF. In this way, even if the encoding is not set in the response of the web server side, the json will be pushed directly without gargling problems.


Fastjson, as the name implies, is fast. There's a lot of performance comparison data out there, so I'm not going to talk about performance.

This is all about its functionality. Perhaps the positioning is not the same, the original fastjson is fast, so in the object serialization and deserialization of a lot of work. But there is a lack of functionality.

I don't know which version has added the key sort by dictionary feature. But there seems to be no way to turn it off. Sometimes I don't want the order of the fields to be out of order, and this problem won't work.

The fastjson version I used was 1.1.14. In addition, fastjson still has some bugs to solve, and it is a relatively obvious bug. For example, in the @jsonfield annotation, the format parameter is used to specify how date-type data is serialized. If you use English or symbols, OK, no problem (e.g. Yyyy-mm-dd), but if Chinese appears in the format, it will be wrong (e.g. Yyyy year, MM month, dd day). And as an experiment, all the annotations have to be placed on the Getter of the property (that is, the getXXX() method). In eclipse, we generally write properties directly, and then generate the Getter and Setter methods automatically. If the properties of the class change in the future, the individual would prefer to simply remove all getters and setters and regenerate them. So if I put all the comments on top of the Getter, I have to be very careful when I delete them.

Another killer is documentation. There is almost no comprehensive documentation to describe or support fastjson. The whole project was headed by a man named wen shao, and there were many uncertainties.


After personal evaluation, I prefer to use Jackson Json. First said documents, Jackson Json web site is the detailed document for each version ((link: http://jackson.codehaus.org/)). In addition, Jackson's Json serialization and deserialization are not necessarily very slow. More importantly, its annotation support is better than fastjson. To take the lexicographically ordered function for example, you can turn off the sorting function by simply adding the @jsonpropertyorder (alphabetic=false) annotation to the entity class. Annotation support for other features is also good.

For example, Date's sequence and deserialization annotation support

@ JsonSerialize (using = DateSerializer. Class)
@ JsonDeserialize (using = DateDeserializer. Class)
Private Date birthday;

This specifies the serialization and deserialization methods for the birthday field. In addition, both annotations are placed directly on the property, not on the Getter.

For the two annotations above, my serializer writes like this

Public class DateSerializer extends JsonSerializer< Date>

Inherited JsonSerializer, specified the serialization type Date in the generic, and then overwrote the following method

@ Override
Public void serialize(Date Date, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException

The date passed into the method is the data to be serialized. You can then display the data as you like, using gen.writeString(formattedDate) before exiting the method. To complete the serialization.

Similarly, my deserializer reads:

Public class DateDeserializer extends. Date>

Inherited the JsonDeserializer, specified the deserialization type Date in the generic, and then overwrote the method as follows

@ Override
Public Date deserialize(JsonParser parser, DeserializationContext context)throws IOException, JsonProcessingException {

The return value of the method in this case is the final content after deserialization. Inside the method you can use parser.gettext () to get what is currently being processed. You can play around with the data, just return the Date you want at the end.


In addition, when making a Service based on Jackson Json, we want to use the idea of generics to write an interface, and the ultimate goal is to make the method return a different type of value depending on the parameter type. I've rarely written generic methods before, but this is a basic problem that stumped me. After looking at Jackson's Json source code, I was inspired to write as follows:

The public < T> T strToObj (String jsonStr Class< T> Clazz)


I'll just write it that way. Suppose I have an object of Result type to deserialize, and I already have a json string jsonStr, then I only need to specify the second parameter clazz to get the object of Result type directly:

Result newResult = jsonProcessService. StrToObj (jsonStr, Result. Class);


This eliminates the need to cast the (Result) type before the method.


The above is just some of my opinions, but also ask colleagues to give more advice.


Related articles: