【问题标题】:Nested Classes that need custom Jackson deserializer需要自定义 Jackson 反序列化器的嵌套类
【发布时间】:2013-12-30 02:35:42
【问题描述】:

我有一个围绕一个复杂类的轻量级包装类,我需要为它编写一个自定义的 Jackson JSON 反序列化器。包装类很简单,只包含一个字符串、一个日期和我的复杂对象作为属性。 Jackson 是否会自动将简单的反序列化器应用于包装器并将我的自定义反序列化器应用于我的复杂对象?自定义反序列化程序自行工作。但是当我尝试序列化包装器时,Jackson 会抛出 Nullpointer 异常。我一定错过了一些概念性的东西。除了我的自定义反序列化器之外,我还必须向我的模块注册另一个序列化器吗?

java.lang.NullPointerException
    at org.codehaus.jackson.impl.ReaderBasedParser._skipWSOrEnd(ReaderBasedParser.java:1477)
    at org.codehaus.jackson.impl.ReaderBasedParser.nextToken(ReaderBasedParser.java:368)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:690)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:580)
    at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2732)
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1863)
    at com.newoak.noc.curve.model.tests.ModelParamsTest.deserializeGraph(ModelParamsTest.java:100)
    at com.newoak.noc.curve.model.tests.ModelParamsTest.testSerializationDeserialization(ModelParamsTest.java:113)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)

尝试反序列化

public ModelParamGraph deserializeGraph(String json) throws JsonGenerationException, JsonMappingException, IOException
    {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null));
        testModule.addSerializer(new SpaceJsonSerializer());
        testModule.addDeserializer(Space.class, new SpaceJsonDeserializer());
        mapper.registerModule(testModule);

        ModelParamGraph space = mapper.readValue(json, ModelParamGraph.class);

        return space;
    }

包装器

public class ModelParamGraph
{
    public String source;

    public Date date;

    @JsonSerialize(using=SpaceJsonSerializer.class)
    @JsonDeserialize(using=SpaceJsonDeserializer.class)
    public Space<TModelParam> paramSpace;

    public ModelParamGraph()
    {
    }

    public ModelParamGraph(String source, Date date)
    {
        setSource(source);
        setDate(date);

        setParamSpace(new Space<TModelParam>());
    }
    //getters and setters
}

【问题讨论】:

  • 我建议您精简所涉及的类,并给我们一个可以重现您的问题的代码。
  • Space 类可以很好地反序列化,我什至可以在 jackson 调用它时逐步通过反序列化器,但随后会出现空指针异常。包装器的默认构造函数在反序列化器之前被调用
  • 我在网上找不到任何关于如何处理嵌套类的自定义反序列化器的示例。

标签: java json spring serialization jackson


【解决方案1】:

如果你可以修改被包装的类,那么你可以使用Jackson的@JsonView注解,这里是full tutorial

第 1 步:像这样创建接口:

public class MyJsonViews {
    public static class Small { }
    public static class Medium extends Small { }
    public static class Large extends Medium { }
}

第 2 步:在 POJO 中注释属性(或方法):

public class Wrapper {
    @JsonView(MyJsonViews.Small.class)
    private String name;

    @JsonView(MyJsonViews.Medium.class)
    private Wrapped wrapped;
    // getters and setters
}

public class Wrapped {
   @JsonView(MyJsonViews.Small.class)
   private String someField;

   @JsonView(MyJsonViews.Medium.class)
   private String anotherField;
  // getters and setters
}

第 3 步:使用新视图进行序列化:

ObjectMapper objectMapper = new ObjectMapper();
// important: this excludes all fields without @JsonView from being serialized
objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
String json = objectMapper.writerWithView(SMyJsonViews.mall.class).writeValueAsString(wrapper);

您的 JSON 现在将只包含带有 @JsonView(MyJsonViews.Small.class) 注释的字段。

如果您无法修改被包装的类,那么您可以使用过滤器方法,描述为here

【讨论】:

  • 序列化不是问题,我正在努力反序列化
  • 抱歉,问题误解了。对反序列化没有任何见解。
猜你喜欢
  • 1970-01-01
  • 2016-02-13
  • 2011-04-12
  • 1970-01-01
  • 2017-05-20
  • 1970-01-01
  • 2016-01-29
  • 1970-01-01
  • 2012-11-18
相关资源
最近更新 更多