ObjectMapper 的一个坑

探讨使用ObjectMapper生成JSON时遇到的变量名大小写冲突问题及解决方法,包括如何避免值被覆盖和推荐的变量命名规范。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用 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 串,同时解析时也会是正确的行为。




### Jackson库中的JsonParser使用方法 Jackson是一个流行的Java库,用于处理JSON数据。`com.fasterxml.jackson.core.JsonParser`类提供了读取JSON流的功能。通过创建`JsonFactory`实例并调用其`createParser()`方法可以获取到`JsonParser`对象。 ```java import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import java.io.File; public class JsonParserExample { public static void main(String[] args) throws Exception { JsonFactory factory = new JsonFactory(); try (JsonParser parser = factory.createParser(new File("example.json"))) { while (!parser.isClosed()) { JsonToken jsonToken = parser.nextToken(); if (jsonToken == null) break; switch (jsonToken) { case START_OBJECT: System.out.println("Start Object"); break; case END_OBJECT: System.out.println("End Object"); break; case FIELD_NAME: System.out.print(parser.getCurrentName() + ": "); // Move to the next token, which will be the value. jsonToken = parser.nextToken(); // Handle field values here... break; default: // Other tokens can also be handled as needed. break; } } } } } ``` 当遇到日期解析错误时,通常是因为默认的日期格式设置不匹配输入字符串格式所引起的[^2]。为了修正这个问题,在配置ObjectMapper的时候应该指定正确的日期格式: ```java import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.annotation.JsonFormat; //... ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); mapper.setDateFormat(sdf); ``` 对于更复杂的场景下可能还需要自定义反序列化器来适配特定的数据结构或业务逻辑需求。 针对Feign请求响应结果被截断的问题,则可以通过调整HTTP客户端实现方式以及优化网络连接参数等方式尝试解决问题[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值