【FastJson源码分析】为什么直接使用JSON.toJSON()枚举类并没有被替换成描述

【FastJson源码分析】为什么直接使用JSON.toJSON()枚举类并没有被替换成描述

  • 简述原因
  1. 因为Json.toJson() 默认取用的是枚举类的 Name 属性
  • 如何获取替换成枚举类描述的JSON 对象
  1. 使用 JSON.toJSON(JSON.toJSONString(instance)) 获取

弄清两者之间的区别,你就知道为什么要这样调用了

JSON.toJSONString()

在研究toJsonString()方法的时候,发现fastjson自己也有一个ObjectSerializer的对象池,当你在实体类中标记了@JSONField注解的时候,它就会根据 实体类的类型返回相对应的ObjectSerializer(序列化器),先看以下代码:

public final void write(Object object) {
        if (object == null) {
            this.out.writeNull();
        } else {
            Class clazz = object.getClass();
            ObjectSerializer writer = this.getObjectWriter(clazz); //  1 号代码

            try {
                writer.write(this, object, (Object)null, (Type)null, 0);  // 2号代码
            } catch (IOException var5) {
                throw new JSONException(var5.getMessage(), var5);
            }
        }
    }
  1. 当实体类中有 @JSONField注解时,1 号代码中将会返回 JavaBeanSerializer,此时2号代码将会调用 javaBeanSerializer的write 方法,期间,FieldSerializer会判断这个Field是不是Enum,如果是,则取 toString的值。关键代码如下:
    if (this.fieldInfo.isEnum) { //here
    	if (this.writeEnumUsingName) {
    		serializer.out.writeString(((Enum)propertyValue).name());
    		return;
    	}
    	if (this.writeEnumUsingToString) {
    		serializer.out.writeString(((Enum)propertyValue).toString());
    		return;
    	}
    }
    
  2. 当实体类中有 @JSONField注解时,1 号代码中将会返回 ASMSerializer_x_xxx如(ASMSerializer_1_User),估计是在项目初始化的期间通过反射产生的,断点调试时此时2号代码会调用Serializable.writeDirect()方法,由于在代码上这个方法是返回 boolean类型的,且名称也不对,并没有对输出做什么操作,猜测是使用了Aop技术(具体是什么没有做深入研究)。这里会直接将所有的Field值转成json格式,而fastjson是默认使用Name属性的,如本例的(MALE/FEMALE)

JSON.toJSON()

toJson时直接返回name属性

if (clazz.isEnum()) {
	return ((Enum)javaObject).name();
}

正是这行代码决定了 JSON.toJSON() 返回的是枚举类的Name 属性。

你可能感兴趣的:(Java后端,笔记)