ObjectMapper 的一个坑

来源:互联网 发布:mysql 查看表 编辑:程序博客网 时间:2024/06/11 20:03

使用 ObjectMapper 去生成 json 串时,有这样一个有意思的现象。

类:

@Data
public class DcmtUseElement {
    
    private String IV_NO_START ;
    private String IV_NO_END ;
    private int IV_CNT ;
    private String IV_TYPE;
    private String REMARKS = "中间业务平台实体卡制卡平台使用凭证";
    
    private String iLoveU = "s";
    private String ILoveU = "b";
    private String remarks = "low";
    
}


使用 ObjectMapper 去获得 json 串,得到这样的结果

{"IV_NO_START":null,"IV_NO_END":null,"IV_CNT":0,"IV_TYPE":null,"REMARKS":"中间业务平台实体卡制卡平台使用凭证","iLoveU":"s","ILoveU":"b","remarks":"中间业务平台实体卡制卡平台使用凭证","iv_NO_START":null,"iv_NO_END":null,"iv_CNT":0,"iv_TYPE":null,"iloveU":"s"}

仔细看上面,发现多出了一些以小写开头的变量。

研究之后发现,这是 ObjectMapper 对象设置了 setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); 的原因。

当不设置时,得到的结果是: {"remarks":"中间业务平台实体卡制卡平台使用凭证","iv_NO_START":null,"iv_NO_END":null,"iv_CNT":0,"iv_TYPE":null,"iloveU":"s"}

发现得到的 json 串完全改写了我们的变量名。

有以下结论:

1.当同时存在仅大小写不同的变量时,无论是否设置 JsonAutoDetect.Visibility.ANY, 均会存在值被覆盖的问题(参考类中的 REMARKS 和 remarks, ILoveU 和 iLoveu)。
2.多数时候,我们还是应该要设置 JsonAutoDetect.Visibility.ANY,否则,出来的 json 串中不含原变量名,设置之后虽然多出了小写对应的变量名,但它起码不会丢失。

结论就是,类中变量名尽量要规范,使用驼峰式。另外,不可存在仅大小写不同的变量名。

-------------------------------------------------------------------- 2017 年7月17日完善

在 benny 大神的指点下,发现 setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);  为什么会起到意想不到的作用:在生成的 json 串中同时生成了原变量名和首字母小写的变量名。上面的 PropertyAccessor.FIELD 原来是要设置在生成 json 串时,对象中的成员的可见性:当传入 PUBLIC_ONLY 时表示只将对象中可见的成员放入 son 串中。而属性一般是不可见的,所以一般不会被放入 json 串中。而该属性的 get 方法是可见的。若定义属性名为 name,且定义了 public  getName 方法,则 json 会根据 getName 推测出 name 属性,并放入 json 串中 - 这是 json 内部的推测规则。而如果一个纯大写字母变量,则从它对应的 set 方法绝对推测不到原属性名,因此 json 串中就没有这个变量了,至于是什么,那就是 json 内部的推断规则了。

如果两个系统间交互的变量名为纯大写,则可以采用 json 提供的变量名映射方式,@JsonProperty("HAS_MORE") 来实现转化 - 不仅仅用于生成 json 串,同时解析时也会是正确的行为。




原创粉丝点击