【问题标题】:Jackson with JSON: Unrecognized field, not marked as ignorable杰克逊与 JSON:无法识别的字段,未标记为可忽略
【发布时间】:2011-05-28 01:43:42
【问题描述】:

我需要将某个 JSON 字符串转换为 Java 对象。我正在使用杰克逊进行 JSON 处理。我无法控制输入 JSON(我从 Web 服务中读取)。这是我的输入 JSON:

{"wrapper":[{"id":"13","name":"Fred"}]}

这是一个简化的用例:

private void tryReading() {
    String jsonStr = "{\"wrapper\"\:[{\"id\":\"13\",\"name\":\"Fred\"}]}";
    ObjectMapper mapper = new ObjectMapper();  
    Wrapper wrapper = null;
    try {
        wrapper = mapper.readValue(jsonStr , Wrapper.class);
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("wrapper = " + wrapper);
}

我的实体类是:

public Class Student { 
    private String name;
    private String id;
    //getters & setters for name & id here
}

我的 Wrapper 类基本上是一个容器对象,用于获取我的学生列表:

public Class Wrapper {
    private List<Student> students;
    //getters & setters here
}

我不断收到此错误,“包装器”返回 null。我不确定缺少什么。有人可以帮忙吗?

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: 
    Unrecognized field "wrapper" (Class Wrapper), not marked as ignorable
 at [Source: java.io.StringReader@1198891; line: 1, column: 13] 
    (through reference chain: Wrapper["wrapper"])
 at org.codehaus.jackson.map.exc.UnrecognizedPropertyException
    .from(UnrecognizedPropertyException.java:53)

【问题讨论】:

  • 我发现这对于避免创建包装类很有用:Map dummy&lt;String,Student&gt; = myClientResponse.getEntity(new GenericType&lt;Map&lt;String, Student&gt;&gt;(){}); 然后Student myStudent = dummy.get("wrapper");
  • JSON 应如下所示: String jsonStr = "{\"students\"\:[{\"id\":\"13\",\"name\":\"Fred\" }]}";如果您在 REST POST 请求中期待 Wrapper 对象
  • 顺便说一句,this 问题的大多数答案实际上回答了一个不同的问题,即与我上面链接的问题相似。
  • 大多数答案有助于在地毯下刷问题而不是实际解决它 :(

标签: java json data-binding jackson


【解决方案1】:

可以使用 Jackson 的类级别注解:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties
class { ... }

它将忽略您在 POJO 中未定义的所有属性。当您只是在 JSON 中寻找几个属性并且不想编写整个映射时非常有用。更多信息请访问Jackson's website。如果你想忽略任何未声明的属性,你应该写:

@JsonIgnoreProperties(ignoreUnknown = true)

【讨论】:

  • Ariel,有没有办法在类外部声明这个?
  • 我正在序列化我不拥有的类(无法修改)。在一个视图中,我想用一组特定的字段进行序列化。在另一个视图中,我想要序列化一组不同的字段(或者可能重命名 JSON 中的属性)。
  • 我必须补充一点,您在为您的课程添加注释时确实需要 (ignoreUnknown = true),否则它将无法正常工作
  • 朱利安,这不是 OP 问题的正确答案。然而,我怀疑人们来到这里是因为他们在谷歌上搜索如何忽略 POJO 中未定义的属性,这是第一个结果,所以他们最终投票赞成这个和 Suresh 的回应(这就是发生在我身上的事情)。虽然最初的问题与想要忽略未定义的属性无关。
  • 这是一个非常愚蠢的默认设置恕我直言,如果你在你的 api 中添加一个属性,整个序列化会失败
【解决方案2】:

你可以使用

ObjectMapper objectMapper = getObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

它将忽略所有未声明的属性。

【讨论】:

  • 这对我不起作用,它仍然在未知属性上失败
  • 能否请您至少粘贴一段代码,您到底在做什么,您可能在那里遗漏了一些东西..通过这样做或使用“@JsonIgnoreProperties(ignoreUnknown = true)”您的问题应该得到解决。总之祝你好运。
  • FWIW -- 我不得不导入这个略有不同的枚举:org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES
  • ^以上适用于 Jackson 2 之前的版本
  • 你也可以像这样链接这些调用:getObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
【解决方案3】:

第一个答案几乎是正确的,但需要的是更改 getter 方法,而不是字段——字段是私有的(并且不是自动检测的);此外,如果两者都是可见的,则 getter 优先于字段。(也有一些方法可以使私有字段可见,但如果你想拥有 getter,那就没什么意义了)

所以 getter 应该命名为getWrapper(),或者注释为:

@JsonProperty("wrapper")

如果您更喜欢 getter 方法名称。

【讨论】:

  • 请详细说明 - 哪个 getter 需要更改或注释?
  • 你的意思是用@JsonGetter("wrapper")注解,对吧?
  • @pedrambashiri 不,我的意思是@JsonProperty。虽然@JsonGetter 是一个合法别名,但它很少使用,因为@JsonProperty 适用于getter、setter 和fields; setter 和 getter 可以通过签名来区分(一个不带参数,返回非 void;另一个带一个参数)。
  • 这就是我一直在寻找的答案!听起来杰克逊很难将源 JSON 映射到您的 POJO,但您可以通过标记 getter 来保证匹配。谢谢!
【解决方案4】:

使用 Jackson 2.6.0,这对我有用:

private static final ObjectMapper objectMapper = 
    new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

和设置:

@JsonIgnoreProperties(ignoreUnknown = true)

【讨论】:

  • 不需要配置注释
  • 类上需要同时配置ObjectMapper和Annotation吗?我猜 objectMapper 将解决所有问题,而无需注释每个类。不过我使用注释。
  • 您不需要在同一类中进行这两种设置。您还可以使用 DI 获取 ObjectMapper 的全局单例实例,以全局设置 FAIL_ON_UNKNOWN_PROPERTIES 属性。
  • 你不需要两者,你可以选择一个或另一个。
【解决方案5】:

可以通过两种方式实现:

  1. 标记 POJO 以忽略未知属性

    @JsonIgnoreProperties(ignoreUnknown = true)
    
  2. 如下配置对POJO/json进行序列化/反序列化的ObjectMapper:

    ObjectMapper mapper =new ObjectMapper();            
    // for Jackson version 1.X        
    mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    // for Jackson version 2.X
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 
    

【讨论】:

  • 为什么这是公认的答案?这只是告诉忽略未知属性,而问题是找到一种方法将 json 包装到该解决方案明确表示要忽略的对象中。
  • 只需使用第一个选项就可以得到很好的答案。
【解决方案6】:

添加 setter 和 getter 解决了问题,我觉得实际的问题是如何解决它,而不是如何抑制/忽略错误。 我收到错误“无法识别的字段..未标记为可忽略..

虽然我在类顶部使用了以下注释,但它无法解析 json 对象并给我输入

@JsonIgnoreProperties(ignoreUnknown = true)

然后我意识到我没有添加 setter 和 getter,在将 setter 和 getter 添加到“Wrapper”和“Student”之后,它就像一个魅力。

【讨论】:

  • 这似乎是唯一真正回答问题的答案。所有其他答案只是将未知属性标记为已忽略,但“包装器”不是未知属性,它是我们试图解析的。
【解决方案7】:

这对我来说非常有用

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(
    DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

@JsonIgnoreProperties(ignoreUnknown = true) 注释没有。

【讨论】:

  • 投反对票,因为它没有回答 OP 的问题。忽略未知属性并不能解决他的问题,但会给他留下一个 Wrapper 实例,其中学生列表为 null 或为空。
【解决方案8】:

这比 All 效果更好,请参考此属性。

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    projectVO = objectMapper.readValue(yourjsonstring, Test.class);

【讨论】:

  • 是的,这就是解决我的问题的问题 - 与这篇文章的标题相符。
  • 答案对我很有效,而且很简单。谢谢
  • 在此之后我的 projectVO 数据为 null.yourjsonstring 有值但 projectVO 字段为 null。有帮助吗?
  • 这确实有效,POJO也不需要任何修改!
【解决方案9】:

如果您使用的是 Jackson 2.0

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

【讨论】:

  • 为什么这个配置对我没有影响?
  • @zhaozhi 这取决于杰克逊版本
【解决方案10】:

根据doc,您可以忽略选定字段或所有未知字段:

 // to prevent specified fields from being serialized or deserialized
 // (i.e. not include in JSON output; or being set even if they were included)
 @JsonIgnoreProperties({ "internalId", "secretKey" })

 // To ignore any unknown properties in JSON input without exception:
 @JsonIgnoreProperties(ignoreUnknown=true)

【讨论】:

    【解决方案11】:

    以下代码对我有用:

    ObjectMapper mapper =new ObjectMapper();    
    mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    

    【讨论】:

      【解决方案12】:

      我尝试了以下方法,它适用于杰克逊的这种 JSON 格式读取。 使用已经建议的解决方案:使用@JsonProperty("wrapper")注释getter

      你的包装类

      public Class Wrapper{ 
        private List<Student> students;
        //getters & setters here 
      } 
      

      我对包装类的建议

      public Class Wrapper{ 
      
        private StudentHelper students; 
      
        //getters & setters here 
        // Annotate getter
        @JsonProperty("wrapper")
        StudentHelper getStudents() {
          return students;
        }  
      } 
      
      
      public class StudentHelper {
      
        @JsonProperty("Student")
        public List<Student> students; 
      
        //CTOR, getters and setters
        //NOTE: If students is private annotate getter with the annotation @JsonProperty("Student")
      }
      

      然而,这会给你格式的输出:

      {"wrapper":{"student":[{"id":13,"name":Fred}]}}
      

      有关更多信息,请参阅https://github.com/FasterXML/jackson-annotations

      【讨论】:

      • 欢迎来到stackoverflow。提示,您可以使用工具栏中的{} 符号来格式化您的代码sn-ps。
      【解决方案13】:

      Jackson 抱怨,因为它在您的类 Wrapper 中找不到名为“wrapper”的字段。这样做是因为您的 JSON 对象有一个名为“wrapper”的属性。

      我认为解决方法是将 Wrapper 类的字段重命名为“wrapper”而不是“students”。

      【讨论】:

      • 谢谢吉姆。我试过了,但没有解决问题。我想知道我是否缺少一些注释..
      • 嗯,当您在 Java 中创建等效数据然后使用 Jackson 以 JSON 格式写入时会发生什么。该 JSON 和上面的 JSON 之间的任何差异都应该是出错的线索。
      • 这个答案对我有用,以问题为例。
      【解决方案14】:

      此解决方案在读取 json 流时是通用的,只需要获取一些字段,而在您的域类中未正确映射的字段可以忽略:

      import org.codehaus.jackson.annotate.JsonIgnoreProperties;
      @JsonIgnoreProperties(ignoreUnknown = true)
      

      详细的解决方案是使用 jsonschema2pojo 之类的工具从 json 响应的 Schema 中自动生成所需的域类,例如 Student。您可以通过任何在线 json 到模式转换器来完成后者。

      【讨论】:

        【解决方案15】:

        由于json属性和java属性的名称不匹配,请如下注释字段学生

        public Class Wrapper {
            @JsonProperty("wrapper")
            private List<Student> students;
            //getters & setters here
        }
        

        【讨论】:

          【解决方案16】:

          如果您想将@JsonIgnoreProperties 应用于应用程序中的所有类,那么最好的方法是覆盖 Spring boot 默认的 jackson 对象。

          在您的应用程序配置文件中定义一个 bean 来创建这样的杰克逊对象映射器。

          @Bean
              public ObjectMapper getObjectMapper() {
                  ObjectMapper mapper = new ObjectMapper();
                  mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                  return mapper;
              }
          

          现在,您不需要标记每个类,它会忽略所有未知属性。

          【讨论】:

            【解决方案17】:

            问题是您在 JSON 中的属性称为“wrapper”,而您在 Wrapper.class 中的属性称为“students”。

            所以要么...

            1. 更正类或 JSON 中的属性名称。
            2. 根据 StaxMan 的评论注释您的属性变量。
            3. 注释设置器(如果有的话)

            【讨论】:

              【解决方案18】:

              不知何故,在 45 个帖子和 10 年后,没有人为我的案例发布正确答案。

              @Data //Lombok
              public class MyClass {
                  private int foo;
                  private int bar;
              
                  @JsonIgnore
                  public int getFoobar() {
                    return foo + bar;
                  }
              }
              

              在我的例子中,我们有一个名为getFoobar() 的方法,但没有foobar 属性(因为它是从其他属性计算而来的)。 @JsonIgnoreProperties 类上不起作用。

              解决方法是用@JsonIgnore注释方法

              【讨论】:

              • 您实际上应该做的是针对您遇到的问题提出具体问题,然后用您的解决方案回答您自己的问题。您在此处添加的内容并不是原始问题所要求的解决方案。如果您将您的具体问题作为问题提出,您将帮助更多的人。
              • @DRaehal Stackoverflow 的主要目的不是(仅)回答一次性问题,而是为未来的谷歌用户提供有用的问题和答案的存储库。这是 Google 上的第一个结果,因此有各种答案。
              • 杰夫阿特伍德会不同意你的看法。 stackoverflow.blog/2011/07/01/….
              • 赞成,因为这也帮助了我。在与@JsonIgnoreProperties 混在一起并添加虚拟成员之后,我发现了这个,它完全符合我的需要。谢谢。
              【解决方案19】:

              要么改变

              public Class Wrapper {
                  private List<Student> students;
                  //getters & setters here
              }
              

              public Class Wrapper {
                  private List<Student> wrapper;
                  //getters & setters here
              }
              

              ----或----

              将您的 JSON 字符串更改为

              {"students":[{"id":"13","name":"Fred"}]}
              

              【讨论】:

                【解决方案20】:

                对我有用的是公开财产。

                【讨论】:

                • 它有帮助!上课也最好公开。
                【解决方案21】:

                就我而言,唯一的一行

                @JsonIgnoreProperties(ignoreUnknown = true)

                也没有用。

                只需添加

                @JsonInclude(Include.NON_EMPTY)
                

                杰克逊 2.4.0

                【讨论】:

                  【解决方案22】:

                  您的意见

                  {"wrapper":[{"id":"13","name":"Fred"}]}
                  

                  表示它是一个Object,带有一个名为“wrapper”的字段,它是一个学生集合。所以我的建议是,

                  Wrapper = mapper.readValue(jsonStr , Wrapper.class);
                  

                  Wrapper 定义为

                  class Wrapper {
                      List<Student> wrapper;
                  }
                  

                  【讨论】:

                    【解决方案23】:

                    新的 Firebase Android 引入了一些巨大的变化;在文档副本下方:

                    [https://firebase.google.com/support/guides/firebase-android]:

                    更新您的 Java 模型对象

                    与 2.x SDK 一样,Firebase 数据库会自动将您传递给 DatabaseReference.setValue() 的 Java 对象转换为 JSON,并且可以使用 DataSnapshot.getValue() 将 JSON 读入 Java 对象。

                    在新的 SDK 中,当使用 DataSnapshot.getValue() 将 JSON 读入 Java 对象时,默认情况下会忽略 JSON 中的未知属性,因此您不再需要 @JsonIgnoreExtraProperties(ignoreUnknown=true)

                    为了在将 Java 对象写入 JSON 时排除字段/getter,现在将注释称为 @Exclude 而不是 @JsonIgnore

                    BEFORE
                    
                    @JsonIgnoreExtraProperties(ignoreUnknown=true)
                    public class ChatMessage {
                       public String name;
                       public String message;
                       @JsonIgnore
                       public String ignoreThisField;
                    }
                    
                    dataSnapshot.getValue(ChatMessage.class)
                    

                    AFTER
                    
                    public class ChatMessage {
                       public String name;
                       public String message;
                       @Exclude
                       public String ignoreThisField;
                    }
                    
                    dataSnapshot.getValue(ChatMessage.class)
                    

                    如果您的 JSON 中有一个不在您的 Java 类中的额外属性,您将在日志文件中看到以下警告:

                    W/ClassMapper: No setter/field for ignoreThisProperty found on class com.firebase.migrationguide.ChatMessage
                    

                    您可以通过在您的类上添加@IgnoreExtraProperties 注释来消除此警告。如果您希望 Firebase 数据库的行为与 2.x SDK 中的行为相同,并在存在未知属性时引发异常,您可以在您的类中添加 @ThrowOnExtraProperties 注释。

                    【讨论】:

                      【解决方案24】:

                      设置public你的类字段不是private

                      public Class Student { 
                          public String name;
                          public String id;
                          //getters & setters for name & id here
                      }
                      

                      【讨论】:

                      • 糟糕的做法 - 这会破坏封装。
                      • 我听说过。
                      • 您的类在用户使用时处于危险之中,因为内部状态可能会通过这些字段发生变化。
                      【解决方案25】:

                      另一种可能性是 application.properties 中的这个属性 spring.jackson.deserialization.fail-on-unknown-properties=false,不需要在您的应用程序中进行任何其他代码更改。并且当您认为合约稳定时,您可以删除此属性或将其标记为 true。

                      【讨论】:

                        【解决方案26】:

                        如果由于某种原因您无法将 @JsonIgnoreProperties 注释添加到您的类中,并且您位于 Web 服务器/容器(例如 Jetty)中。您可以在自定义提供程序中创建和自定义 ObjectMapper

                        import javax.ws.rs.ext.ContextResolver;
                        import javax.ws.rs.ext.Provider;
                        
                        import com.fasterxml.jackson.annotation.JsonInclude.Include;
                        import com.fasterxml.jackson.databind.DeserializationFeature;
                        import com.fasterxml.jackson.databind.ObjectMapper;
                        
                        @Provider
                        public class CustomObjectMapperProvider implements ContextResolver<ObjectMapper> {
                        
                            private ObjectMapper objectMapper;
                        
                            @Override
                            public ObjectMapper getContext(final Class<?> cls) {
                                return getObjectMapper();
                            }
                        
                            private synchronized ObjectMapper getObjectMapper() {
                                if(objectMapper == null) {
                                    objectMapper = new ObjectMapper();
                                    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                                }
                                return objectMapper;
                            }
                        }
                        

                        【讨论】:

                          【解决方案27】:

                          这对我来说非常有效

                          objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                          

                          【讨论】:

                            【解决方案28】:

                            这可能与 OP 遇到的问题不同,但如果有人遇到与我相同的错误,那么这将帮助他们解决问题。当我使用来自不同依赖项的 ObjectMapper 作为 JsonProperty 注释时,我得到了与 OP 相同的错误。

                            这行得通:

                            import com.fasterxml.jackson.databind.ObjectMapper;
                            import com.fasterxml.jackson.annotation.JsonProperty;
                            

                            不工作:

                            import org.codehaus.jackson.map.ObjectMapper; //org.codehaus.jackson:jackson-mapper-asl:1.8.8
                            import com.fasterxml.jackson.annotation.JsonProperty; //com.fasterxml.jackson.core:jackson-databind:2.2.3
                            

                            【讨论】:

                            • 谢谢! import com.fasterxml.jackson.annotation.JsonProperty 为我工作,而不是另一个:-)
                            • omfg 这可要了我的命! ty
                            【解决方案29】:

                            我通过简单地更改我的 POJO 类的 setter 和 getter 方法的签名解决了这个问题。我所要做的就是更改 getObject 方法以匹配映射器正在寻找的内容。在我的情况下,我最初有一个 getImageUrl,但 JSON 数据有 image_url,这让映射器无法工作。我将 setter 和 getter 都更改为 getImage_url 和 setImage_url

                            【讨论】:

                            • 你显然是对的:如果你想要的名字是 xxx_yyy 调用它的方法是 getXxx_yyy 和 setXxx_yyy。这很奇怪,但它有效。
                            【解决方案30】:

                            POJO 应该被定义为

                            响应类

                            public class Response {
                                private List<Wrapper> wrappers;
                                // getter and setter
                            }
                            

                            包装类

                            public class Wrapper {
                                private String id;
                                private String name;
                                // getters and setters
                            }
                            

                            和映射器读取值

                            Response response = mapper.readValue(jsonStr , Response.class);
                            

                            【讨论】:

                            • 差不多。不是wrappers,而是wrapper
                            • @Frans 哈哈,感谢您发现错误。我很自然地使用复数来表示集合。但根据 OP 的问题,它应该是单数的。
                            猜你喜欢
                            • 2012-01-14
                            • 1970-01-01
                            • 2020-04-19
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2015-03-20
                            相关资源
                            最近更新 更多