简体   繁体   English

用Jackson以两种不同的方式序列化一个班级

[英]Serialize one class in two different ways with Jackson

In one of our projects we use a java webapp talking to a MongoDB instance. 在我们的一个项目中,我们使用java webapp与MongoDB实例进行通信。 In the database, we use DBRefs to keep track of some object relations. 在数据库中,我们使用DBRefs来跟踪一些对象关系。 We (de)serialize with POJO objects using jackson (using mongodb-jackson-mapper). 我们使用jackson(使用mongodb-jackson-mapper)使用POJO对象进行序列化。

However, we use the same POJOs to then (de)serialize to the outside world, where our front end deals with presenting the JSON. 但是,我们使用相同的POJO然后(de)序列化到外部世界,我们的前端处理呈现JSON。

Now, we need a way for the serialization for the outside world to contain the referenced object from a DBRef (so that the UI can present the full object), while we obviously want to have the DBRef written to the database, and not the whole object. 现在,我们需要一种方法让外部世界的序列化包含来自DBRef的引用对象(以便UI可以呈现完整对象),而我们显然希望将DBRef写入数据库,而不是整个宾语。

Right now I wrote some untested static nested class code: 现在我写了一些未经测试的静态嵌套类代码:

public static class FooReference {
    public DBRef<Foo> foo;

    // FIXME how to ensure that this doesn't go into the database?
    public Foo getFoo() {
        return foo.fetch();
    }
}

Ideally I would like a way to annotate this so that I could (de)serialize it either with or without the getFoo() result, probably depending on some configuration object. 理想情况下,我想要一种方法来注释这个,以便我可以(或)使用或不使用getFoo()结果序列化它,可能取决于一些配置对象。 Is this possible? 这可能吗? Do you see a better way of going about doing this? 你有没有看到更好的方法来做这件事?

From looking at options, it seems you can annotate properties to only be shown if a given View is passed to the ObjectMapper used for serialization. 通过查看选项,您似乎可以注释属性,只有在给定的View传递给用于序列化的ObjectMapper才会显示。 You could thus edit the class: 你可以编辑这个类:

public static class FooReference {
    public DBRef<Foo> foo;

    @JsonView(Views.WebView.class)
    public Foo getFoo() {
        return foo.fetch();
    }
}

and provide: 并提供:

class Views {
    static class WebView { }
}

and then serialize after creating a configuration with the correct view: 然后在使用正确的视图创建配置后序列化:

SerializationConfig conf = objectMapper.getSerializationConfig().withView(Views.WebView.class);
objectMapper.setSerializationConfig(conf);

Which would then serialize it. 然后将序列化它。 Not specifying the view when serializing with the MongoDB wrapper would mean the method would be ignored. 使用MongoDB包装器进行序列化时不指定视图意味着该方法将被忽略。 Properties without a JsonView annotation are serialized by default, a behaviour you can change by specifying: 默认情况下,没有JsonView批注的属性会被序列化,您可以通过指定以下内容来更改此行为:

objectMapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION, false);

More info is available on the Jackson Wiki . 更多信息可在Jackson Wiki上获得

There are still other alternatives, too, it turns out: there are Jackson MixIns which would let you override (de)serialization behaviour of parts of a class without modifying the class itself, and as of Jackson 2.0 (very recent release) there are filters , too. 还有其他的选择,事实证明:有一些Jackson MixIns可以让你覆盖(de)类的部分行为而不修改类本身,而且从Jackson 2.0(最近的版本)开始就有过滤器也是。

Use a custom JSONSerializer and apply your logic in the serialize method: 使用自定义JSONSerializer并在serialize方法中应用您的逻辑:

public static class FooReference {
    public DBRef<Foo> foo;

    @JsonSerialize(using = CustomSerializer.class)
    public Foo getFoo() {
        return foo.fetch();
    }
}

public class CustomSerializer extends JsonSerializer<Object> {
   public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
       throws IOException, JsonProcessingException {
     // jgen.writeObjectField ...
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM