通常,fastjson在序列化及反序列化枚举时,一般以下几种策略:

1).根据枚举的name值序列化及反序列化(默认)

2).根据枚举的ordinal序列化及反序列化

3).根据枚举的toString方法序列化,但是反序列仍采取默认的策略

这显然对我们的业务处理不够灵活,考虑以下一种情况:

有一个文章类,它有标题,内容等属性,其中有一个属性是枚举类,表示文章是否通过审核。

如下:

public class Article {private String title;

    private String content;private AuditStatus status;public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
}public AuditStatus getStatus() {
return status;
} public void setStatus(AuditStatus status) {
this.status = status;
}
}

对应的枚举类型,它包含一个标志状态的code:

public enum AuditStatus {
AUDITING(1), PASSED(2), FAILED(3); private int code; AuditStatus(int code){
this.code = code;
} public int getCode(){
return code;
}
public static AuditStatus convert(int code){
AuditStatus[] enums = AuditStatus.values();
for(AuditStatus e : enums){
if(e.code == code)
return e;
}
return null;
}
}

注意,上述的code并不等于枚举的ordinal。

我们希望AuditStatus序列化和反序列化的都是根据其code值来。

比如序列化成如下字符串:

{"content":"This is content","status":1,"title":"Article 1"} 

并能正确反序列化得到的Article对象中的status属性是AuditStatus.AuditStatus。

我们逐个对应上述的策略来看看是否能满足我们的要求:

方法一:会将status序列化成AUDITING。因此不行

方法二:会将status根据ordinal来序列化,得到的结果为0,也不行。

方法三:我们可以override toString方法,这样可以是的序列化的结果正确,但是反序列化过程仍然不行。

那么没有其他方法可以满足我们的业务需求了嘛?

网上给出的一种方法如下,修改Article类:

 public class Article {

     private String title;

     private String content;

     private AuditStatus statusCode;

     public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} @JSONField(serialize = false)
public AuditStatus getStatusCode() {
return statusCode;
} @JSONField(deserialize = true)
public void setStatusCode(AuditStatus statusCode) {
this.statusCode = statusCode;
} @JSONField(name = "status")
public int getStatus(){
return statusCode.getCode();
} @JSONField(name = "status")
public AuditStatus setStatus(int code){
return AuditStatus.convert(code);
}
}

这种方式屏蔽了默认的序列化及反序列化过程:行7(将status重命名成statusCode),行25-33(禁止了statusCode的序列化);并增加了自定义的序列化过程(行35-43)。

我测试了这种方式,虽然能在序列化时得到正常结果,但是却无法正常发序列化。

测试代码:

public class SerializeTest {
public static void main(String[] args){
Article article = new Article();
article.setTitle("Article 1");
article.setContent("This is content");
article.setStatusCode(AuditStatus.AUDITING); String str = JSON.toJSONString(article);
System.out.println(str); Article article1 = JSON.parseObject(str, Article.class);
System.out.println(article1.getStatusCode());
}
}

输出的结果:

因此这种做法并不可行,而且会让代码的可读性变差。

因此我推荐一种我尝试过成功的方法:编写自定义的编解码器,在通过@JsonField的serializeUsing和deserializeUsing属性指定编解码过程中使用的编解码器。

添加自定义的编解码器:

//ObjectSerializer和ObjectDeserializer分别是fastjson的编码器和解码器接口
public class AudtiStautsCodec implements ObjectSerializer, ObjectDeserializer {
//反序列化过程
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
Object value = parser.parse();
return value == null ? null : (T) AuditStatus.convert(TypeUtils.castToInt(value));
} //暂时还不清楚
public int getFastMatchToken() {
return 0;
} //序列化过程
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
serializer.write(((AuditStatus)object).getCode());
}
}

修改Article类,在status字段上增加@JsonField属性,并指定编解码器:

public class Article {

    private String title;

    private String content;

    @JSONField(serializeUsing = AudtiStautsCodec.class, deserializeUsing = AudtiStautsCodec.class)
private AuditStatus status; public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public AuditStatus getStatus() {
return status;
} public void setStatus(AuditStatus status) {
this.status = status;
} }

在通过之前的测试代码测试一下结果是否正确:

public class SerializeTest {
public static void main(String[] args){
Article article = new Article();
article.setTitle("Article 1");
article.setContent("This is content");
article.setStatus(AuditStatus.AUDITING); String str = JSON.toJSONString(article);
System.out.println(str); Article article1 = JSON.parseObject(str, Article.class);
System.out.println(article1.getStatus());
}
}

结果如下:

最新文章

  1. C语言多文件编译
  2. UpdatePanel无法导出下载文件
  3. 在 C++ 代码中使用 UE4 插件---Using a plugin in C++ code
  4. 如何让Vim显示dos下的^M符号
  5. Open gl 的不规则图形的4联通种子递归填充和扫描线种子递归填充算法实现
  6. 百度SEO优化
  7. iframe自适应高度的问题
  8. javascript创建类的6种方式
  9. 他的第一个NDK的Demo
  10. ubuntu14.04安装配置jdk1.8.0_25
  11. pat1021-1030
  12. ITU-T G.1080 IPTV的体验质量(QoE)要求 (Quality of experience requirements for IPTV services)
  13. 锋利的jquery 事件 动画
  14. C#版的 Escape() 和 Unescape()
  15. springMVC01,使用xml
  16. JVM的基本结构及其各部分详解(二)
  17. Spring集成mybatis时mybatis的映射XML配置
  18. 开源数据流管道-Luigi vs Azkaban vs Oozie vs Airflow
  19. logstash日志分析的配置和使用(转)
  20. 测试redis集群的两种方式:分片和哨兵

热门文章

  1. 1065 A+B and C (64bit) (20分)(水)
  2. PTA | 1008 数组元素循环右移问题 (20分)
  3. 使用Homebrew在Mountain Lion上安装MySQL
  4. Centos7如何安装MySQL
  5. NHibernate COUNT(*) 统计问题
  6. XSS(跨站脚本攻击)简单讲解
  7. Git应用详解第七讲:Git refspec与远程分支的重要操作
  8. QMS产品 - MasterControl 质量管理活动
  9. 运输层--------运输层与网络层的关系、UDP、TCP
  10. Connections in Galaxy War ZOJ - 3261 (并查集)