文章描述了一个在使用Jackson进行反序列化时遇到的问题,即JSON对象中的大写属性名无法正确映射到JavaBean的小写字段。问题源于Jackson默认将属性名转为小写。解决方案包括使用@JsonProperty注解明确指定属性名,或者禁用DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES特性。 摘要由CSDN通过智能技术生成

参考链接: https://www.baeldung.com/jackson-annotations

  1. 遇到的问题

之前和第三方对接,返回的接口中的属性名称是拼音字母大写,奇怪,反序列化的时候好多字段都为空,没设置进去。

因为对接前,我先用 IntelliJ IDEA 的 Http Client 工具调试接口,返回的属性并不为空,但是用 RestTemplate 调用接口反序列化后的字段都为空。跟踪代码后,发现在收集反序列化后的对象的属性名称的时候,把大写字段名称都改写成了小写字母。而 json 字符串的名称都是大写的,但是在 Bean 的属性名称集合中的名称都是小写的,自然就匹配不上了。所以,反序列化的时候,大写字段的值都为空了。

下面用一段代码来复现一下 :

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
 * @author shifengqiang 2023/2/22 16:20
public class TestBean {
    private int id;
    private String BH;
    public String getBH() {
        return BH;
    public void setBH(String BH) {
        this.BH = BH;
    public int getId() {
        return id;
    public void setId(int id) {
        this.id = id;
    @Override
    public String toString() {
        return "{\"TestBean\":{"
                + "\"id\":\"" + id + " \""
                + ",\"BH\":\"" + BH + " \""
                + "}}";
    public static void main(String[] args) throws Exception {
        String json = "{\"id\":1,\"BH\":\"aaa\"}";
        ObjectMapper mapper = new ObjectMapper();
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        TestBean test = mapper.readValue(json, TestBean.class);
        String json1 = mapper.writeValueAsString(test);
        System.out.println("序列化前的 json :");
        System.out.println(json);
        System.out.println();
        System.out.println("反序列化后的对象:");
        System.out.println(test);
        System.out.println();
        System.out.println("反序列化后的 bean 再序列化后的 json :");
        System.out.println(json1);
        System.out.println();

下面是控制台的输出结果:

序列化前的 json :
{"id":1,"BH":"aaa"}
反序列化后的对象:
{"TestBean":{"id":"1 ","BH":"null "}}
反序列化后的 bean 再序列化后的 json :
{"id":1,"bh":null}
  1. 从对 test 对象打印的结果可以看出,BH 属性并没有序列化成功。

  2. 从对 test 对象的序列化的结果可以看出,BH 属性打印出来之后就变成小写的 bh json 属性了。

  3. 源码跟踪

对 jackson 原理感兴趣的同学可以跟踪代码,读一下实现代码。

  1. 收集 bean 的属性名称 :
    com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector#collectAll() 方法中对 bean 的 field、get 方法、set 方法进行了收集。jackson 会忽略所有 private 字段、方法。最终收集到的 field 、get/set 方法名作为了 属性名称集合 。反序列化的时候,如果 json 中的属性名在属性名称集合中找不到的话,就没法设置值了。
  2. 把大写名称改为小写的具体实现方法 :
    在 com.fasterxml.jackson.databind.util.BeanUtil#legacyManglePropertyName() 方法中把大写名称改为了小写。
* Method called to figure out name of the property, given * corresponding suggested name based on a method or field name. * @param basename Name of accessor/mutator method, not including prefix * ("get"/"is"/"set") protected static String legacyManglePropertyName(final String basename, final int offset) final int end = basename.length(); if (end == offset) { // empty name, nope return null; // next check: is the first character upper case? If not, return as is char c = basename.charAt(offset); char d = Character.toLowerCase(c); if (c == d) { return basename.substring(offset); // otherwise, lower case initial chars. Common case first, just one char StringBuilder sb = new StringBuilder(end - offset); sb.append(d); int i = offset+1; for (; i < end; ++i) { c = basename.charAt(i); d = Character.toLowerCase(c); if (c == d) { sb.append(basename, i, end); break; sb.append(d); return sb.toString();

下面两种方法任意一种都可以解决大小写不匹配的问题 :

  1. 在 BH 字段上加注解 @JsonProperty(“BH”) 来显式的声音属性的名称是 BH 。
  2. 在 getBH() 方法或者 setBH() 这两个方法中的任意一个方法上加 @JsonProperty(“BH”) 注解。
面对不遵守驼峰命名规则的接口,比如属行首字母大写,这样导致使用Jackson解析出来的对象的属性均为空,经过跟踪源码发现,是由于其根据getters方法解析的属性属性字母都变为了小写,这就导致无法解析了出现了jackson Unrecognized field 的问题。 @Data public class JobType { private int jobType;
默认情况下类的成员变量以小写字母开头,  当需要以大写开头时,系统在编译时或者swagger在传递参数时都会自动将大写变为小写,带来一些不便, 寻找后采取以下解决办法: 1. 解决swagger传递时的大写问题   @JsonProperty  //这个注解帮助实现大写传递     private String L1; //country;     @JsonProperty     priv...
springboot使用默认的jackson序列化实体为json字符串时的问题, 属性名只有大小写差异时,后面的会被忽略 public static void main(String[] args) throws JsonProcessingException { TestVO testVO = new TestVO(); ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.
官方WIKI:https://github.com/FasterXML/jackson-databind/wiki jackson 1.x和2.x版本的注解是放置在不同的包下的 1.x是在jackson core jar包org.codehaus.jackson.annotate下 2.x是在jackson-databind包com.fasterxml.jackson.annot