public class Test { private String name; @JSONField(serializeUsing = ToStringSerializer.class) private Integer age; public static void main(String[] args) { Test test = new Test(); test.setName("张三"); test.setAge(null); System.out.println(JSON.toJSONString(test)); } // get set }
上面不会进入ToStringSerializer.writer 方法。
//这里不会执行if (object == null) { out.writeNull(); }
7条答案
按热度按时间ttcibm8c1#
版本1.2.76也不行
qyzbxkaa2#
请问对于
你想要的预期效果是这样的吗:
{"age":"null","name":"张三"}
syqv5f0l3#
@Tloops 我的预期是当age 为null 时,能进入ToStringSerializer里面的write方法。
因为方法里面有一段代码
if (object == null) { out.writeNull(); }
但是现在这种null情况不会进入这个序列化方法,所以,上面这段代码是不会生效的。(ToStringSerializer是fastjson自带的,其他自定义序列化方法也是不会有null情况进入。)所以我觉得这是一个bug
ykejflvf4#
从源码跟了一下,现在的代码,对于null值处理时,针对Number、String、Boolean、Collection这四种类型是不支持JSONField.serializeUsing的(这里是做特例处理造成的,不知道是否有什么考量)
有两段相关代码
1.JavaBeanSerializer中,对于属性值为null处理时,会特殊处理几个特定类型,对于这里相关的Number.class类型处理时,会优先考虑定义的特性(SerializerFeature),如果null不写则直接跳过处理,所以也就不会再进注解自定义的处理器,相关代码为
JavaBeanSerializer 350行 } else if (Number.class.isAssignableFrom(fieldClass)) { int defaultMask = SerializerFeature.WriteNullNumberAsZero.mask; final int mask = defaultMask | SerializerFeature.WriteMapNullValue.mask; if ((!writeAsArray) && (serialzeFeatures & mask) == 0 && (out.features & mask) == 0) { continue; }
2.如果这里我们开启WriteMapNullValue,执行了FieldSerializer(实现JSONField处理的地方)了,则会因为下述代码直写null而不触发JSONField.serializeUsing 的处理逻辑
//FieldSerializer 233行 if (Number.class.isAssignableFrom(runtimeFieldClass)) { out.writeNull(features, SerializerFeature.WriteNullNumberAsZero.mask); return; } else if (String.class == runtimeFieldClass) { out.writeNull(features, SerializerFeature.WriteNullStringAsEmpty.mask); return; } else if (Boolean.class == runtimeFieldClass) { out.writeNull(features, SerializerFeature.WriteNullBooleanAsFalse.mask); return; } else if (Collection.class.isAssignableFrom(runtimeFieldClass) || runtimeFieldClass.isArray()) { out.writeNull(features, SerializerFeature.WriteNullListAsEmpty.mask); return; }
mrzz3bfm5#
从源码跟了一下,现在的代码,对于null值处理时,针对Number、String、Boolean、Collection这四种类型是不支持JSONField.serializeUsing 的(这里是做特例处理造成的,不知道是否有什么考量)
有两段相关代码
1.JavaBeanSerializer中,对于属性值为null处理时,会特殊处理几个特定类型,对于这里相关的Number.class类型处理时,会优先考虑定义的特性(SerializerFeature),如果null不写则直接跳过处理,所以也就不会再进注解自定义的处理器,相关代码为
JavaBeanSerializer 350行 } else if (Number.class.isAssignableFrom(fieldClass)) { int defaultMask = SerializerFeature.WriteNullNumberAsZero.mask; final int mask = defaultMask | SerializerFeature.WriteMapNullValue.mask; if ((!writeAsArray) && (serialzeFeatures & mask) == 0 && (out.features & mask) == 0) { continue; }
2.如果这里我们开启WriteMapNullValue,执行了FieldSerializer(实现JSONField处理的地方)了,则会因为下述代码直写null而不触发JSONField.serializeUsing 的处理逻辑
//FieldSerializer 233行 if (Number.class.isAssignableFrom(runtimeFieldClass)) { out.writeNull(features, SerializerFeature.WriteNullNumberAsZero.mask); return; } else if (String.class == runtimeFieldClass) { out.writeNull(features, SerializerFeature.WriteNullStringAsEmpty.mask); return; } else if (Boolean.class == runtimeFieldClass) { out.writeNull(features, SerializerFeature.WriteNullBooleanAsFalse.mask); return; } else if (Collection.class.isAssignableFrom(runtimeFieldClass) || runtimeFieldClass.isArray()) { out.writeNull(features, SerializerFeature.WriteNullListAsEmpty.mask); return; }
看源码下来有一个体验就是... 现在的实现里特例处理的情景太多了,而且没有注解说明,不知道因为什么考量引入的特例处理... ... 这就导致了能看清楚引发问题的逻辑是什么... ... 但是不敢改..
izj3ouym6#
回归到这个问题的解决办法,个人觉得有一个方案是
1.业务上设定 0、null、空值同一个业务含义
2.然后就是转不转出来都没关系了.... 需要转出来null的话,用
JSON.toJSONString(test, SerializerFeature.WriteMapNullValue)
这种写法即可
jqjz2hbq7#
@RLin2015New 仔细看了你的解析,非常感谢你的回答。我原先的需求是。对于Number类型的字段。在serializeUsing时,可以生成一个新的字段(比如BigDecimal amount 生成String amountStr = "5")。用于前端展示,解决浮点数精度丢失问题。后面发现这个null时不进入,也就不能适配null的情况。所以也就用其他方法代替。