java fastjson如何自定义转换含枚举类型对象(编程技巧)
2016-06-17 17:41
861 查看
在使用fastjson对java对象进行序列化和反序列化时,如果含有枚举类型,默认会根据枚举变量的ordinal值进行反序列且序列化时显示枚举字面代表的字符串。经常这种行为不是我们想要的,那么如何进行定制化枚举类型的序列化和反序列? 举例如下
对象内部定义了状态码枚举类StatusCodeEnum,包含两个实例OK、SERVER_ERROR。
{“id”:1,”status”:200}
显然,如果直接用Json.parseObject()方法进行反序列化,会报如下错误信息:
Exception in thread “main” com.alibaba.fastjson.JSONException: parse
enum com.netwaymedia.exhibition.nio.common.dto.Msg$StatusCodeEnum
error, value : 200 at
com.alibaba.fastjson.parser.deserializer.EnumDeserializer.deserialze(EnumDeserializer.java:48)
at
com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer.parseField(DefaultFieldDeserializer.java:33)
原因分析:前面已经提过,fastjson默认使用ordinal值去查找对应的枚举实例,显示是获取不到的,所以抛出异常,需要修改status值为0才运行OK。
{“id”:1,”status”:”OK”}
显示不是我们所期待的原始字符串
{“id”:1,”status”:200}
如何解决上述两大问题?
思路是通过修改字段名为statusCode,并用JSONField注解该字段不进行序列和反序列化,但是提供getStatus/setStatus方法来定制化枚举变量statusCode的序列和反序列,完美的解决前面提到的两大问题。
这个方法我在网上还没看到过,是我自己尝试出来的,特别拿出来跟大家分享,不用谢,请叫我雷锋。
问题引出
假设待序列化和反序列化java对象结构如下public class Msg { private int id; private StatusCodeEnum status; public int getId() { return id; } public void setId(int id) { this.id = id; } public StatusCodeEnum getStatus() { return status; } public void setStatus(StatusCodeEnum status) { this.status = status; } public static enum StatusCodeEnum { OK(200, "正常"), SERVER_ERROR(500, "服务器错误"); private static final Map<Integer, StatusCodeEnum> CODE_MAP = new HashMap<Integer, StatusCodeEnum>(); static { for (StatusCodeEnum typeEnum : StatusCodeEnum.values()) { CODE_MAP.put(typeEnum.getCode(), typeEnum); } } StatusCodeEnum(int code, String meaning) { this.code = code; this.meaning = meaning; } public int getCode() { return code; } public String getMeaning() { return meaning; } public static StatusCodeEnum getEnum(Integer code) { return CODE_MAP.get(code); } private final int code; private final String meaning; } }
对象内部定义了状态码枚举类StatusCodeEnum,包含两个实例OK、SERVER_ERROR。
反序列化问题
如何使用fastjson成功反序列如下json串?{“id”:1,”status”:200}
显然,如果直接用Json.parseObject()方法进行反序列化,会报如下错误信息:
Exception in thread “main” com.alibaba.fastjson.JSONException: parse
enum com.netwaymedia.exhibition.nio.common.dto.Msg$StatusCodeEnum
error, value : 200 at
com.alibaba.fastjson.parser.deserializer.EnumDeserializer.deserialze(EnumDeserializer.java:48)
at
com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer.parseField(DefaultFieldDeserializer.java:33)
原因分析:前面已经提过,fastjson默认使用ordinal值去查找对应的枚举实例,显示是获取不到的,所以抛出异常,需要修改status值为0才运行OK。
序列化问题
如果使用JSON.toJSONString()方法对上述Msg对象进行序列化,会得到如下json串{“id”:1,”status”:”OK”}
显示不是我们所期待的原始字符串
{“id”:1,”status”:200}
如何解决上述两大问题?
优雅的解决方案
答案就在于fastjson提供注解JSONField。通过JSONField可灵活控制字段的序列化和反序列,重新修改Msg结构如下:public class Msg { private int id; private StatusCodeEnum statusCode; public int getId() { return id; } public void setId(int id) { this.id = id; } @JSONField(name = "status") public int getStatus() { return statusCode.getCode(); } @JSONField(name = "status") public void setStatus(int code) { this.statusCode = StatusCodeEnum.getEnum(code); } @JSONField(serialize = false) public StatusCodeEnum getStatusCode() { return statusCode; } @JSONField(deserialize = false) public void setStatusCode(StatusCodeEnum statusCode) { this.statusCode = statusCode; } public static enum StatusCodeEnum { OK(200, "正常"), BAD_REQUEST(400, "服务器出错"); private static final Map<Integer, StatusCodeEnum> CODE_MAP = new HashMap<Integer, StatusCodeEnum>(); static { for (StatusCodeEnum typeEnum : StatusCodeEnum.values()) { CODE_MAP.put(typeEnum.getCode(), typeEnum); } } StatusCodeEnum(int code, String meaning) { this.code = code; this.meaning = meaning; } public int getCode() { return code; } public String getMeaning() { return meaning; } public static StatusCodeEnum getEnum(Integer code) { return CODE_MAP.get(code); } private final int code; private final String meaning; } }
思路是通过修改字段名为statusCode,并用JSONField注解该字段不进行序列和反序列化,但是提供getStatus/setStatus方法来定制化枚举变量statusCode的序列和反序列,完美的解决前面提到的两大问题。
这个方法我在网上还没看到过,是我自己尝试出来的,特别拿出来跟大家分享,不用谢,请叫我雷锋。
相关文章推荐
- jackson、Gson反序列化 泛型
- fastjson处理接口时的一个问题
- C#编程中枚举类型的使用教程
- c#数据的序列化和反序列化(推荐版)
- 枚举的用法详细总结
- PHP中Enum(枚举)用法实例详解
- .net实现序列化与反序列化实例解析
- c#入门之枚举和结构体使用详解(控制台接收字符串以相反的方向输出)
- 理解C#中的枚举(简明易懂)
- C#枚举中的位运算权限分配浅谈
- C#实现的json序列化和反序列化代码实例
- C++基础入门教程(四):枚举和指针
- FileShare枚举的使用小结(文件读写锁)
- Java枚举类用法实例
- 枚举窗口句柄后关闭所有窗口示例
- Json序列化和反序列化方法解析
- 解析PHP多种序列化与反序列化的方法
- javascript模拟枚举的简单实例
- 深入剖析JavaScript中的枚举功能
- 深入理解Java对象的序列化与反序列化的应用