如何让Jackson JSON生成的数据包含的中文以unicode方式编码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何让Jackson JSON生成的数据包含的中文以unicode方式编码相关的知识,希望对你有一定的参考价值。

参考技术A Jackson JSON其实在默认设置下已经具备了对Unicode编码的JSON数据进行解析。所欠缺的就是在序列化对象时缺少相应的步骤。好在Jackson JSON框架允许我们自定义序列化方法。那么我们就来写一个序列化类:

复制代码代码如下:

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 >> 12) & 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('"');//写入JSON中字符串的开头引号
for (char c : str.toCharArray())
if (c >= 0x80)
writeUnicodeEscape(gen, c); // 为所有非ASCII字符生成转义的unicode字符
else
// 为ASCII字符中前128个字符使用转义的unicode字符
int code = (c < ESCAPE_CODES.length ? ESCAPE_CODES[c] : 0);
if (code == 0)
gen.writeRaw(c); // 此处不用转义
else if (code < 0)
writeUnicodeEscape(gen, (char) (-code - 1)); // 通用转义字符
else
writeShortEscape(gen, (char) code); // 短转义字符 (\n \t ...)



gen.writeRaw('"');//写入JSON中字符串的结束引号



这个序列化类将要对应用中所有使用Jackson JSON的地方全都用一种方法来处理字符串类型。光有了方法还不行,还要对它进行注册。让Jackson JSON在序列化对象的时候使用刚刚定义好的方法:

复制代码代码如下:

if (objectMapper== null)
objectMapper= new ObjectMapper();
//当找不到对应的序列化器时 忽略此字段
objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
//使Jackson JSON支持Unicode编码非ASCII字符
CustomSerializerFactory serializerFactory= new CustomSerializerFactory();
serializerFactory.addSpecificMapping(String.class, new StringUnicodeSerializer());
objectMapper.setSerializerFactory(serializerFactory);
//支持结束


接下来我们来做一个测试用的对象,验证我们的代码:

复制代码代码如下:

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



从代码上可以看出,我们并没有对String类型的属性强制指定用何种序列与反序列方法。然后我们来构造测试用例:

复制代码代码如下:

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("鸟叔");
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("转换为JSON后的数据:%s", JSONUtil.toJSON(objSrc)));
DemoObj objDes= JSONUtil.fromJSON(json, DemoObj.class);
if(objDes==null)
logger.info("反序列化失败");
else
logger.info("反序列化成功");
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
logger.info(String.format("标识:%d", objDes.getSid()));
logger.info(String.format("姓名:%s", objDes.getStuName()));
logger.info(String.format("性别:%s", objDes.getSex()==true?"男":"女"));
logger.info(String.format("生日:%s", sdf.format(objDes.getBirthday())));
logger.info(String.format("登录日期:%s", sdf.format(objDes.getLogTime())));




看一下输出:

复制代码代码如下:

转换为JSON后的数据:"sid":1,"stuName":"\u9E1F\u53D4","sex":true,"birthday":"1977-12-31","logTime":"2012-12-04 19:31:57"
反序列化成功
标识:2
姓名:江南Style
性别:男
生日:2012-07-15 00:00:00
登录日期:2012-12-04 19:22:36

我们看到,已经成功将中文字符显示成为了Unicode编码的数据。同样,我们之前构造的Unicode编码的数据,在不经过任何修改的情况下成功显示出来了。

细心的朋友也许观察到了,在测试用的对象定义代码中,针对同样Date类型的属性“birthday”和“logTime”,我们指定了不同的序列化与反序列化方法。让我们来看烂这两个有什么不同:

复制代码代码如下:

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);



复制代码代码如下:

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();




复制代码代码如下:

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);



复制代码代码如下:

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();


本回答被提问者和网友采纳

以上是关于如何让Jackson JSON生成的数据包含的中文以unicode方式编码的主要内容,如果未能解决你的问题,请参考以下文章

如何让Jackson JSON生成的数据包含的中文以unicode方式编码

Jackson JSON 库:如何实例化包含抽象字段的类

当使用 Spring MVC for REST 时,如何让 Jackson 漂亮地打印呈现的 JSON?

Jackson 序列化期间如何跳过 Optional.empty 字段?

Spring无法在Maven中存在Jackson的情况下转换JSON

如何在JAVA中用JACKSON映射一个JSON中的数组,这个数组可以包含不同类型的对象作为项目?