As we all know, Jackson JSON is known for its speed, convenience and flexibility. The previous article described the use of annotations as a way to specify how to serialize an object to JSON, and how to deserialize a JSON data onto an object. But the drawback is the treatment of Chinese. Of course, the drawback is that, by default, Jackson JSON does not convert non-ASCII characters, such as Chinese, into a form such as \UFFFF. This means {"name": "Zhang San"} instead of {"name": "\u5f20\u4e09"} is displayed by default. So why is there such a demand? In the HTTP protocol, we can specify the content encoding of the Data header section. such as: "GBK", "UTF-8" and so on. If you set it correctly, then OK, the former represents the data you can handle correctly. However, if you set the error, it will be garbled for Chinese characters. Two sets of application system docking, it may be used on both sides of the default encoding, if one side to modify the default encoding will cause unpredictable consequences for the application. Therefore, if you can develop in a long-term perspective, no matter what encoding you set, it will not garbled the data. Because, the universal code--unicode is used here.
OK, the question comes out, how can we solve it? By experimenting, Jackson JSON already has parsing of Unicode encoded JSON data in the default settings. What is missing is a lack of steps when serializing an object. Fortunately, the Jackson JSON framework allows us to customize the serialization method. So we're going to write a serialization class:
Copy CodeThe code is as follows:
Import java.io.IOException;
Import org.codehaus.jackson.JsonGenerationException;
Import Org.codehaus.jackson.JsonGenerator;
Import org.codehaus.jackson.JsonProcessingException;
Import Org.codehaus.jackson.impl.JsonWriteContext;
Import Org.codehaus.jackson.map.JsonSerializer;
Import Org.codehaus.jackson.map.SerializerProvider;
Import Org.codehaus.jackson.util.CharTypes;
public class Stringunicodeserializer extends Jsonserializer<string> {
Private final char[] Hex_chars = "0123456789ABCDEF". ToCharArray ();
Private final int[] Escape_codes = Chartypes.get7bitoutputescapes ();
private void Writeunicodeescape (Jsongenerator gen, char c) throws IOException {
Gen.writeraw (' \ \ ');
Gen.writeraw (' u ');
Gen.writeraw (hex_chars[(c >>) & 0xF]);
Gen.writeraw (hex_chars[(c >> 8) & 0xF]);
Gen.writeraw (hex_chars[(c >> 4) & 0xF]);
Gen.writeraw (Hex_chars[c & 0xF]);
}
private void Writeshortescape (Jsongenerator gen, char c) throws IOException {
Gen.writeraw (' \ \ ');
Gen.writeraw (c);
}
@Override
public void serialize (String str, Jsongenerator Gen,
Serializerprovider provider) throws IOException,
jsonprocessingexception {
int status = ((Jsonwritecontext) Gen.getoutputcontext ()). WriteValue ();
Switch (status) {
Case Jsonwritecontext.status_ok_after_colon:
Gen.writeraw (': ');
Break
Case Jsonwritecontext.status_ok_after_comma:
Gen.writeraw (', ');
Break
Case Jsonwritecontext.status_expect_name:
throw new Jsongenerationexception ("Can not write String value here");
}
Gen.writeraw (' "');//write the opening quotation marks of a string in JSON
for (char C:str.tochararray ()) {
if (c >= 0x80) {
Writeunicodeescape (Gen, C); Generates escaped Unicode characters for all non-ASCII characters
}else {
Use escaped Unicode characters for the first 128 characters in an ASCII character
int code = (C < escape_codes.length? Escape_codes[c]: 0);
if (code = = 0) {
Gen.writeraw (c); Do not escape here
}else if (Code < 0) {
Writeunicodeescape (Gen, (char) (-code-1)); Universal Escape Character
}else {
Writeshortescape (Gen, (char) code); Short escape character (\ n \ t ...)
}
}
}
Gen.writeraw (' "');//write the closing quotation mark of a string in JSON
}
}
This serialization class will have a way to handle string types in all places in the app where Jackson JSON is used. The light has a way not to, but also to register it. Let Jackson json use the method that was just defined when serializing the object:
Copy CodeThe code is as follows:
if (objectmapper== null) {
Objectmapper= new Objectmapper ();
This field is ignored when the corresponding serializer cannot be found
Objectmapper.configure (SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
Enable Jackson JSON to support Unicode encoding of non-ASCII characters
Customserializerfactory serializerfactory= new Customserializerfactory ();
Serializerfactory.addspecificmapping (String.class, New Stringunicodeserializer ());
Objectmapper.setserializerfactory (serializerfactory);
Support End
}
Next we'll do a test object to validate our code:
Copy CodeThe code is as follows:
Import Java.util.Date;
Import Net.csdn.blog.chaijunkun.util.DateDeserializer;
Import Net.csdn.blog.chaijunkun.util.DateSerializer;
Import Net.csdn.blog.chaijunkun.util.DateTimeDeserializer;
Import Net.csdn.blog.chaijunkun.util.DateTimeSerializer;
Import Org.codehaus.jackson.annotate.JsonPropertyOrder;
Import org.codehaus.jackson.map.annotate.JsonDeserialize;
Import org.codehaus.jackson.map.annotate.JsonSerialize;
@JsonPropertyOrder (alphabetic= false)
public class Demoobj {
Private Integer SID;
Private String Stuname;
Private Boolean sex;
@JsonSerialize (using= dateserializer.class)
@JsonDeserialize (using= datedeserializer.class)
Private Date birthday;
@JsonSerialize (using= datetimeserializer.class)
@JsonDeserialize (using= datetimedeserializer.class)
Private Date LogTime;
Getters and Setters
}
As you can see from the code, we do not force a String type property to specify what sequence and inverse sequence method to use. Then we'll construct the test case:
Copy CodeThe code is as follows:
Import Java.text.SimpleDateFormat;
Import Java.util.Calendar;
Import Java.util.Date;
Import NET.CSDN.BLOG.CHAIJUNKUN.JSON.DEMOOBJ;
Import Net.csdn.blog.chaijunkun.util.JSONUtil;
Import Org.apache.log4j.Logger;
public class Jsontest {
private static Logger logger= Logger.getlogger (jsontest.class);
private static String json= "{\" sid\ ": 2,\" stuname\ ": \" \u6c5f\u5357style\ ", \" sex\ ": True,\" birthday\ ": \" 2012-07-15\ " , \ "logtime\": \ "2012-12-04 19:22:36\"} ";
public static void Main (string[] args) {
Demoobj objsrc= new Demoobj ();
Objsrc.setsid (1);
Objsrc.setstuname ("Uncle Bird");
Objsrc.setsex (TRUE);
Calendar calendar= calendar.getinstance ();
Calendar.set (1977, Calendar.december, 31, 0, 0, 0);
Objsrc.setbirthday (Calendar.gettime ());
Objsrc.setlogtime (New Date ());
Logger.info (String.Format ("Data converted to JSON:%s", Jsonutil.tojson (OBJSRC)));
Demoobj objdes= Jsonutil.fromjson (JSON, demoobj.class);
if (objdes==null) {
Logger.info ("deserialization failed");
}else{
Logger.info ("deserialization succeeded");
SimpleDateFormat sdf= New SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss");
Logger.info (String.Format ("ID:%d", Objdes.getsid ()));
Logger.info (String.Format ("Name:%s", Objdes.getstuname ()));
Logger.info (String.Format ("Gender:%s", Objdes.getsex () ==true? " Male ":" female "));
Logger.info (String.Format ("Birthday:%s", Sdf.format (Objdes.getbirthday ()));
Logger.info (String.Format ("Login Date:%s", Sdf.format (Objdes.getlogtime ()));
}
}
}
Look at the output:
Copy CodeThe code is as follows:
Data converted to JSON: {"Sid": 1, "Stuname": "\u9e1f\u53d4", "Sex": true, "Birthday": "1977-12-31", "LogTime": "2012-12-04 19:31:57 "}
Deserialization succeeded
ID: 2
Name: Jiangnan style
Gender: Male
Birthday: 2012-07-15 00:00:00
Login Date: 2012-12-04 19:22:36
We see that the Chinese characters have been successfully displayed as Unicode encoded data. Similarly, the Unicode encoded data that we constructed previously was successfully displayed without any modification.
The attentive friend may have observed that in the object definition code for the test, we specify different serialization and deserialization methods for properties "Birthday" and "logtime" of the same date type. Let's see what the difference is between the two:
Copy CodeThe code is as follows:
Import java.io.IOException;
Import Java.text.SimpleDateFormat;
Import Java.util.Date;
Import Org.codehaus.jackson.JsonGenerator;
Import org.codehaus.jackson.JsonProcessingException;
Import Org.codehaus.jackson.map.JsonSerializer;
Import Org.codehaus.jackson.map.SerializerProvider;
public class Datetimeserializer extends Jsonserializer<date> {
@Override
public void serialize (date date, Jsongenerator Gen, Serializerprovider provider)
Throws IOException, Jsonprocessingexception {
SimpleDateFormat sdf=new SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss");
String formatteddate= Sdf.format (date);
Gen.writestring (formatteddate);
}
}
Copy CodeThe code is as follows:
Import java.io.IOException;
Import Java.text.SimpleDateFormat;
Import Java.util.Calendar;
Import Java.util.Date;
Import Org.codehaus.jackson.JsonParser;
Import org.codehaus.jackson.JsonProcessingException;
Import Org.codehaus.jackson.map.DeserializationContext;
Import Org.codehaus.jackson.map.JsonDeserializer;
public class Datetimedeserializer extends Jsondeserializer<date> {
@Override
Public Date Deserialize (jsonparser parser, Deserializationcontext context)
Throws IOException, Jsonprocessingexception {
String dateformat= "Yyyy-mm-dd HH:mm:ss";
SimpleDateFormat sdf= New SimpleDateFormat (DateFormat);
try{
String fielddata= Parser.gettext ();
Return Sdf.parse (FieldData);
}catch (Exception e) {
Calendar ca= calendar.getinstance ();
Ca.set (1970, Calendar.january, 1, 0, 0, 0);
return Ca.gettime ();
}
}
}
Copy CodeThe code is as follows:
Import java.io.IOException;
Import Java.text.SimpleDateFormat;
Import Java.util.Date;
Import Org.codehaus.jackson.JsonGenerator;
Import org.codehaus.jackson.JsonProcessingException;
Import Org.codehaus.jackson.map.JsonSerializer;
Import Org.codehaus.jackson.map.SerializerProvider;
public class Dateserializer extends Jsonserializer<date> {
@Override
public void serialize (date date, Jsongenerator Gen, Serializerprovider provider)
Throws IOException, Jsonprocessingexception {
SimpleDateFormat sdf=new SimpleDateFormat ("Yyyy-mm-dd");
String formatteddate= Sdf.format (date);
Gen.writestring (formatteddate);
}
}
Copy CodeThe code is as follows:
Import java.io.IOException;
Import Java.text.SimpleDateFormat;
Import Java.util.Calendar;
Import Java.util.Date;
Import Org.codehaus.jackson.JsonParser;
Import org.codehaus.jackson.JsonProcessingException;
Import Org.codehaus.jackson.map.DeserializationContext;
Import Org.codehaus.jackson.map.JsonDeserializer;
public class Datedeserializer extends Jsondeserializer<date> {
@Override
Public Date Deserialize (jsonparser parser, Deserializationcontext context)
Throws IOException, Jsonprocessingexception {
String dateformat= "YYYY-MM-DD";
SimpleDateFormat sdf= New SimpleDateFormat (DateFormat);
try{
String fielddata= Parser.gettext ();
Return Sdf.parse (FieldData);
}catch (Exception e) {
Calendar ca= calendar.getinstance ();
Ca.set (1970, Calendar.january, 1, 0, 0, 0);
return Ca.gettime ();
}
}
}
From the code we can see that Datetimeserializer and Datetimedeserializer are finer granularity than Dateserializer and Datedeserializer, adding attributes of specific time. This is very common in the application development, the birthday information we often know the month and day can be, and landing time often need to be more detailed. From the example we can see that even the same type, by making different sequences and inverse sequence methods, we can flexibly get the shape of the data we want. The above test cases have been packaged.
Click to download
Add:
Recently there is a need to make changes to the data when serializing and deserializing the object, and when the data source value is found to be empty, the resulting JSON display should be changed to "visitor". But I do. Specifies that the serializer and the deserializer are not valid. The program simply cannot go to the specified code. Then I came to the conclusion that Jackson JSON, when deserializing an object, does not walk the custom Deserializer if the corresponding property in the JSON data is null, and similarly, when you set a property value of an object to NULL, you do not go through the custom serializer when serializing it to JSON. So if you have a similar requirement, try to judge and modify it in hard code before serialization and deserialization, and never expect a serializer and a deserializer.
Articles you may be interested in:
- Parsing the serialization of objects in the Jackson Library of Java and data-generic binding
- Instance parsing data binding in the Jackson Library of Java
- Introduction to the use of the Jackson Library in Java and its Tree model learning tutorial
- Parsing Java's use of the streaming API in the Jackson Library
- A tutorial that uses Jackson to convert a Java object to JSON
- A case study of Jackson's usage
- An example of the use of the Objectmapper class in the Jackson Library of Java
How to make the data that Jackson JSON generates contain Unicode encoding in Chinese