【问题标题】:Jackson JSON not able to deserialize array of elements with custom root name?Jackson JSON 无法反序列化具有自定义根名称的元素数组?
【发布时间】:2014-07-27 16:31:06
【问题描述】:

我有一个如下所示的 Json:

{
  "testEntities" : [ {
    "id" : 1,
    "floatNumber" : 0.006117165,
    "floatNumberObject" : 0.15273619,
    "intNumber" : -1155869325,
    "intNumberObject" : 431529176,
    "doubleNumber" : 0.41008081149220166,
    "doubleNumberObject" : 0.20771484130971707,
    "shortNumber" : 9364,
    "shortNumberObject" : 13977,
    "booleanValue" : true,
    "booleanValueObject" : true,
    "byteValue" : -79,
    "charValue" : "e",
    "charValueObject" : "b",
    "creationDate" : 86400000
  }, {
    "id" : 2,
    "floatNumber" : 0.9874208,
    "floatNumberObject" : 0.45285606,
    "intNumber" : -1154715079,
    "intNumberObject" : 1260042744,
    "doubleNumber" : 0.9014476240300544,
    "doubleNumberObject" : 0.49682259343089075,
    "shortNumber" : 483,
    "shortNumberObject" : 18322,
    "booleanValue" : false,
    "booleanValueObject" : true,
    "byteValue" : -73,
    "charValue" : "c",
    "charValueObject" : "r",
    "creationDate" : 172800000
  } ]
}

当我尝试反序列化它时,它失败了:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Root name 'testEntities' does not match expected ('TestObject[]') for type

我已经启用了数组反序列化:

objectMapper.enable(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY);

显然,testEntities 是杰克逊一无所知的自定义名称。 TestObject 类有一个我创建的名为 JsonRootNamePlural 的自定义注释,当根元素是一个集合而不是单个实例时使用:

@JsonRootName("testEntity")
@JsonRootNamePlural("testEntities")
public class TestObject {
   ...
}

系统的其他地方也需要这个注解。

我希望它以与使用 @JsonRootName 注释相同的方式使用它,但数组除外。所以它可以查找 JsonRootName 指示的根元素,如果没有找到,它可以查找 @JsonRootNamePlural。 Jackson 应忽略 JSON 中的所有其他根名称。

问题是,我应该重写或自定义什么来引入这种行为?

非常感谢任何帮助或指点,谢谢!

【问题讨论】:

    标签: java arrays json jackson deserialization


    【解决方案1】:

    找到了我自己的问题的答案:需要在对象映射器上设置 JacksonAnnotationIntrospector 的自定义实例,它会覆盖 findRootName 方法,并检查该类是否为数组,如果是则查找自定义注释数组组件类,如下所示:

        @Override
        public PropertyName findRootName(AnnotatedClass ac) {
            // if this is an array, look for JsonRootNamePlural annotation in
            // the base type for the array (the so called array component)
            if (ac.getRawType().isArray()) {
                Class<?> arrayComponent = ac.getRawType().getComponentType();
    
                JsonRootNamePlural ann = arrayComponent.getAnnotation(JsonRootNamePlural.class);
                if (ann != null) {
                    return PropertyName.construct(ann.value(), null);
                }
    
            }
    
            // super class will look for default @JsonRootName annotation
            return super.findRootName(ac);
        }
    

    希望这对其他人有帮助,

    干杯!

    【讨论】:

      【解决方案2】:

      非常感谢!)您真的很有帮助!我是创建注释的新手,所以我会写下我是怎么做的,也许创建自己的会很容易。 这是一个注解类:

      @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @JacksonAnnotation
      public @interface JsonRootNamePlural {
          String value();
      }
      

      我的 Introspector 类:

      class ArrayRootNameAnnotationIntrospector extends JacksonAnnotationIntrospector {
          @Override
          public PropertyName findRootName(AnnotatedClass ac) {
              if (ac.getRawType().isArray()) {
                  Class<?> arrayComponent = ac.getRawType().getComponentType();
      
                  JsonRootNamePlural ann = arrayComponent.getAnnotation(JsonRootNamePlural.class);
                  if (ann != null) {
                      return PropertyName.construct(ann.value(), null);
                  }
      
              }
              return super.findRootName(ac);
          }
      }
      

      还有 JsonUtil 类:

           public static Object readArrayFromJson(String responseString,Class arrayClazz) {
              ObjectMapper mapper = new ObjectMapper();
              mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
              mapper.setAnnotationIntrospector(new ArrayRootNameAnnotationIntrospector());
                  mapper.findAndRegisterModules();
                  try {
                      return mapper.readValue(responseString, arrayClazz);
                  } catch (IOException e) {
                      throw new RuntimeException(e);
                  }
              }
      

      请注意 readArrayFromJson() 方法中的 arrayClazz 变量应该是数组的类(例如 MyObject[].class)

      【讨论】:

        猜你喜欢
        • 2013-10-25
        • 2012-07-27
        • 2016-03-22
        • 2020-01-14
        • 1970-01-01
        • 2020-05-27
        • 2017-01-10
        • 1970-01-01
        • 2012-02-08
        相关资源
        最近更新 更多