简体   繁体   English

Jackson:如何防止字段序列化(同时保持反序列化)

[英]Jackson: how to prevent field serialization (while keeping deserialization)

I'd like to go further on what this question was about, I've been roaming SO for a solid hour now without finding anything. 我想进一步探讨这个问题 ,我一直在漫游一个小时,但没有发现任何问题。

Basically, what I'm trying to do is having a property properly instanciated through Jackson internal reflection algorithm during deserialization but having this same property not serialized when it comes to serialization. 基本上,我想做的是在反序列化期间具有通过Jackson内部反射算法正确实例化的属性,但是在进行序列化时,该属性序列化。

I know about @JsonIgnore and @JsonIgnoreProperties but apparently I can't seem to use them right : either my property is correctly deserialized when I feed Jackson a proper map of properties but it also appears in the serialized results, either (when using @JsonIgnore ) it is not serialized (which is wanted) but also not deserialized (not wanted). 我知道@JsonIgnore@JsonIgnoreProperties但显然我似乎并没有正确使用它们:当我向Jackson喂入正确的属性映射时,要么我的属性正确反序列化,要么在序列化结果中也出现(当使用@JsonIgnore ),它不会序列化(不需要),也不会反序列化(不需要)。

Example : 范例:

public class Foo {

    /* This is the property I want to be instanciated by Jackson upon deserialization
     * but not serialized upon serialization
     */
    private final Object bar = null;

    public Object getBar() {
        return bar;
    }
}

To make things worse, as you can see, the property is final (this is why I'm keen on using Jackson reflection ability upon Foo instanciation through deserialization). 如您所见,更糟的是,该属性是最终属性(这就是为什么我热衷于在通过反序列化对Foo实例化时使用Jackson反射功能)。 I've read on potential solution about annotating the setter and the getter differently but I'd like to keep this property final if possible. 我已经阅读了有关以不同方式对setter和getter进行注释的潜在解决方案,但我希望尽可能保留此属性的最终状态。 If not possible , I'd settle for a non-final property. 如果不可能的话 ,我会选择非最终财产。

I would appreciate answers not suggesting custom serializer/deserializer, my code base is currently free of such and if the solution could be of minimal impact, that would be perfect. 我会很高兴看到没有建议使用自定义序列化器/反序列化器的答案,我的代码库目前没有此类代码,如果解决方案的影响最小,那将是完美的。 Again, I'm no Jackson expert so if what I'm asking is not possible I'll obviously accept alternative answers. 再说一次,我不是杰克逊专家,所以如果我要问的是不可能的,我显然会接受其他答案。

I've also read this thread on github but none of the suggested ways of implementation have actually been implemented at the moment. 我也在github上阅读了该线程,但是目前尚未实际实现任何建议的实现方式。

Thanks 谢谢


EDIT : to make things clearer 编辑:使事情更清楚

public class Foo {

    private final String bar = null;

    public String getBar() {
        return bar;
    }

    @Override
    public String toString() {
        return bar;
    }
}


public void testMethod() throws IOException {
        String json = "{\"bar\":\"Value\"}";
        ObjectMapper mapper = new ObjectMapper();
        Foo foo = mapper.readValue(json, Foo.class);
        System.out.println(foo); // should have a bar property set to "Value"
        System.out.println(mapper.writeValueAsString(foo)); // should return an empty JSON object
}

I am not sure whether it is elegant solution but you can use MixIn feature. 我不确定这是否是一种优雅的解决方案,但您可以使用MixIn功能。 You have to create new interface which could look like below: 您必须创建新的界面,如下所示:

interface FooMixIn {

    @JsonIgnore
    String getBar();
}

Assume that your POJO looks like this: 假设您的POJO如下所示:

class Foo {

    private final String bar = null;

    public String getBar() {
        return bar;
    }

    @Override
    public String toString() {
        return bar;
    }
}

Now you have to tell Jackson that you want to ignore this property: 现在,您必须告诉Jackson您想忽略此属性:

String json = "{\"bar\":\"Value\"}";
System.out.println(json);
ObjectMapper deserializeMapper = new ObjectMapper();
deserializeMapper.addMixInAnnotations(Foo.class, FooMixIn.class);
System.out.println(deserializeMapper.readValue(json, Foo.class));

Above example prints: 上面的示例打印:

{"bar":"Value"}
null

Without deserializeMapper.addMixInAnnotations(Foo.class, FooMixIn.class); 没有deserializeMapper.addMixInAnnotations(Foo.class, FooMixIn.class); line above program prints: 程序打印上方的一行:

{"bar":"Value"}
Value

EDIT 1 编辑1


If you want to achieve result like you showed you have to create two ObjectMapper s and customize them. 如果要获得ObjectMapper的结果,则必须创建两个ObjectMapper并对其进行自定义。 See below example: 请参见以下示例:

String json = "{\"bar\":\"Value\"}";
ObjectMapper deserializerMapper = new ObjectMapper();
Foo foo = deserializerMapper.readValue(json, Foo.class);
System.out.println("Foo object: " + foo);

ObjectMapper serializerMapper = new ObjectMapper();
serializerMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
serializerMapper.addMixInAnnotations(Foo.class, FooMixIn.class);
System.out.println("JSON: " + serializerMapper.writeValueAsString(foo));

For serialization you have to use one instance and for deserialization you have to use another instance. 对于序列化,您必须使用一个实例,对于反序列化,您必须使用另一个实例。

Starting with Jackson 2.6 , a property can be marked as read- or write-only. Jackson 2.6开始,可以将属性标记为只读或只写。 It's simpler than hacking the annotations on both accessors (for non-final fields) and keeps all the information in one place. 这比修改两个访问器上的注释(对于非最终字段)更简单,并将所有信息都保存在一个地方。 It's important to note that a final field is considered writable by default by Jackson. 重要的是要注意,Jackson默认认为final字段可写的。

However, it's not enough for a final field to allow deserialization, because you can't have a setter on that field: it needs to be set via the constructor, either directly or using a builder or another type that can be deserialized by Jackson. 但是,对于最后一个字段而言,允许反序列化是不够的,因为您不能在该字段上使用setter:它需要通过构造函数直接或使用生成器或可以由Jackson进行反序列化的另一种类型进行设置。 When using the constructor with the properties as parameters, you need to specify which parameter corresponds to which property, using @JsonProperty : 当使用带有属性作为参数的构造函数时,需要使用@JsonProperty指定哪个参数对应于哪个属性:

public class Foo {
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private final String bar;

    public Foo(@JsonProperty("bar") String bar) {
        this.bar = bar;
    }

    public String getBar() {
        return prop;
    }
}

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

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