首页 文章

Jackson json反序列化,忽略了json的根元素

提问于
浏览
37

如何忽略json中的父标记?

这是我的json

String str = "{\"parent\": {\"a\":{\"id\": 10, \"name\":\"Foo\"}}}";

这是从json映射的类 .

public class RootWrapper {
  private List<Foo> foos;

  public List<Foo> getFoos() {
    return foos;
  }

  @JsonProperty("a")
  public void setFoos(List<Foo> foos) {
    this.foos = foos;
  }
 }

这是测试公共类JacksonTest {

@Test
public void wrapRootValue() throws Exception {
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
    mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    String str = "{\"parent\": {\"a\":{\"id\": 10, \"name\":\"Foo\"}}}";

    RootWrapper root = mapper.readValue(str, RootWrapper.class);

    Assert.assertNotNull(root);
}

我收到错误::

org.codehaus.jackson.map.JsonMappingException: Root name 'parent' does not match expected ('RootWrapper') for type [simple type, class MavenProjectGroup.mavenProjectArtifact.RootWrapper]

我找到了Jackson注释给出的解决方案::

(a) Annotate you class as below

  @JsonRootName(value = "parent")
  public class RootWrapper {

  (b) It will only work if and only if ObjectMapper is asked to wrap.
    ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);

任务完成!!

Jackson 反序列化的另一种打嗝:(

如果'DeserializationConfig.Feature.UNWRAP_ROOT_VALUE配置',它解包所有jsons,虽然我的类没有注释@JsonRootName(value =“rootTagInJson”),但是没有被安装 .

我只想在使用@JsonRootName注释类时解包根标记,否则不要解包 .

以下是解包根标记的用例 .

###########################################################
     Unwrap only if the class is annotated with @JsonRootName.
  ############################################################

我对Jackson源代码的ObjectMapper进行了一些小改动,并创建了一个新版本的jar . 1.将此方法放在ObjectMapper中

// Ash:: Wrap json if the class being deserialized, are annotated
// with @JsonRootName else do not wrap.
private boolean hasJsonRootName(JavaType valueType) {
    if (valueType.getRawClass() == null)
        return false;

    Annotation rootAnnotation =  valueType.getRawClass().getAnnotation(JsonRootName.class);
    return rootAnnotation != null;
}


    2. Edit ObjectMapper method :: 
    Replace 
       cfg.isEnabled(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE)
    with
       hasJsonRootName(valueType)

    3. Build your jar file and use it.

3 回答

  • 0

    https://github.com/FasterXML/jackson-databind中的TestRootName.java中获取的示例可能会提供更好的方法 . 特别是使用withRootName(“”):

    private ObjectMapper rootMapper()
    {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
        mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
        return mapper;
    }
    
    public void testRootUsingExplicitConfig() throws Exception
    {
        ObjectMapper mapper = new ObjectMapper();
        ObjectWriter writer = mapper.writer().withRootName("wrapper");
        String json = writer.writeValueAsString(new Bean());
        assertEquals("{\"wrapper\":{\"a\":3}}", json);
    
        ObjectReader reader = mapper.reader(Bean.class).withRootName("wrapper");
        Bean bean = reader.readValue(json);
        assertNotNull(bean);
    
        // also: verify that we can override SerializationFeature as well:
        ObjectMapper wrapping = rootMapper();
        json = wrapping.writer().withRootName("something").writeValueAsString(new Bean());
        assertEquals("{\"something\":{\"a\":3}}", json);
        json = wrapping.writer().withRootName("").writeValueAsString(new Bean());
        assertEquals("{\"a\":3}", json);
    
        bean = wrapping.reader(Bean.class).withRootName("").readValue(json);
        assertNotNull(bean);
    }
    
  • 12

    我在Spring中开发了一个类似的问题 . 我必须支持一个非常异构的API,其中一些有根元素,另一个没有 . 我找不到比实时配置此属性更好的解决方案 . 遗憾的是, Jackson 不支持每类根元素展开 . 无论如何,有人可能会觉得这很有帮助 .

    @Component
    public class ObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper {
        private void autoconfigureFeatures(JavaType javaType) {
            Annotation rootAnnotation = javaType.getRawClass().getAnnotation(JsonRootName.class);
            this.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, rootAnnotation != null);
        }
    
        @Override
        protected Object _readMapAndClose(JsonParser jsonParser, JavaType javaType) throws IOException, JsonParseException, JsonMappingException {
            autoconfigureFeatures(javaType);
            return super._readMapAndClose(jsonParser, javaType);
        }
    
    }
    
  • 32

    作为Seagabond的更新帖子,如果您希望在编写参数值时具有相同的效果,则可以覆盖其他写入方法 .

    @Component
    public class ObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper {
        private void autoconfigureFeatures(Object value) {
            JavaType javaType = _typeFactory.constructType(value.getClass());
            autoconfigureFeatures(javaType);
        }
        private void autoconfigureFeatures(JavaType javaType) {
            Annotation rootAnnotation = javaType.getRawClass().getAnnotation(JsonRootName.class);
            this.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, rootAnnotation != null);
        }
    
        @Override
        public void writeValue(DataOutput out, Object value) throws IOException {
            autoconfigureFeatures(value);
            super.writeValue(out, value);
        }
    
        @Override
        public void writeValue(Writer w, Object value) throws IOException, JsonGenerationException, JsonMappingException {
            autoconfigureFeatures(value);
            super.writeValue(w, value);
        }
    
        @Override
        public byte[] writeValueAsBytes(Object value) throws JsonProcessingException {
            autoconfigureFeatures(value);
            return super.writeValueAsBytes(value);
        }
    
        @Override
        public String writeValueAsString(Object value) throws JsonProcessingException {
            autoconfigureFeatures(value);
            return super.writeValueAsString(value);
        }
    
        @Override
        protected Object _readMapAndClose(JsonParser jsonParser, JavaType javaType) throws IOException, JsonParseException, JsonMappingException {
            autoconfigureFeatures(javaType);
            return super._readMapAndClose(jsonParser, javaType);
        }
    
    }
    

相关问题