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

Java Jackson:如何防止字段序列化(同时保持反序列化),java,json,serialization,jackson,Java,Json,Serialization,Jackson,我想更进一步,我已经漫游了整整一个小时,什么也没找到 基本上,我要做的是在反序列化过程中通过Jackson内部反射算法正确实例化一个属性,但在序列化时,将这个相同的属性不序列化 我知道@JsonIgnore和@JsonIgnoreProperties但显然我不能正确地使用它们:或者当我向Jackson提供正确的属性映射时,我的属性被正确地反序列化,但是它也出现在序列化结果中,或者(当使用@JsonIgnore时)它没有被序列化(这是需要的)但也没有反序列化(不需要) 例如: public cla

我想更进一步,我已经漫游了整整一个小时,什么也没找到

基本上,我要做的是在反序列化过程中通过Jackson内部反射算法正确实例化一个属性,但在序列化时,将这个相同的属性序列化

我知道
@JsonIgnore
@JsonIgnoreProperties
但显然我不能正确地使用它们:或者当我向Jackson提供正确的属性映射时,我的属性被正确地反序列化,但是它也出现在序列化结果中,或者(当使用
@JsonIgnore
时)它没有被序列化(这是需要的)但也没有反序列化(不需要)

例如:

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;
    }
}
更糟糕的是,正如您所看到的,该属性是final(这就是为什么我热衷于通过反序列化在
Foo
实例化上使用Jackson反射功能)。我已经读过关于以不同方式注释setter和getter的潜在解决方案,但如果可能的话,我希望保留这个属性为最终属性。如果不可能的话,我会选择非最终财产

如果答案不建议使用自定义序列化器/反序列化器,我将不胜感激,我的代码库目前没有此类问题,如果解决方案的影响最小,那将是完美的。再说一次,我不是杰克逊专家,所以如果我问的不可能,我显然会接受其他答案

我也读过,但目前没有一种建议的实施方式真正得到实施

谢谢


编辑:使事情更清楚

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
}

我不确定这是否是一个优雅的解决方案,但您可以使用该功能。您必须创建如下所示的新界面:

interface FooMixIn {

    @JsonIgnore
    String getBar();
}
假设您的
POJO
如下所示:

class Foo {

    private final String bar = null;

    public String getBar() {
        return bar;
    }

    @Override
    public String toString() {
        return bar;
    }
}
现在,您必须告诉
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));
上面的示例打印:

{"bar":"Value"}
null
没有
反序列化apper.addMixinNotation(Foo.class,FooMixIn.class)程序打印上方的行:

{"bar":"Value"}
Value

编辑1


如果您想获得您展示的结果,您必须创建两个
ObjectMapper
s并对其进行自定义。请参见以下示例:

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));
对于序列化,您必须使用一个实例;对于反序列化,您必须使用另一个实例。

从开始,属性可以标记为只读或只写。这比破解两个访问器上的注释(对于非最终字段)更简单,并将所有信息保存在一个地方。需要注意的是,默认情况下Jackson认为最后一个字段是可写的

但是,对于允许反序列化的最终字段来说,这是不够的,因为您不能在该字段上设置setter:它需要通过构造函数进行设置,可以直接设置,也可以使用生成器或Jackson可以反序列化的其他类型。当使用属性作为参数的构造函数时,需要使用
@JsonProperty
指定哪个参数对应于哪个属性:

公共类Foo{
@JsonProperty(access=JsonProperty.access.WRITE_ONLY)
私人最终字符串栏;
public Foo(@JsonProperty(“bar”)字符串栏){
这个.bar=bar;
}
公共字符串getBar(){
返回道具;
}
}

该死+1因为你的回答完全符合你所描述的,并向我介绍了Jackson的MixIn,但这也让我意识到我把序列化/反序列化过程搞混了<<我编辑了我的问题,如果你知道这样做的任何方式,它回答了我的真正需要,我很乐意接受你的回答。现在我真的不明白你想做什么。您希望在序列化过程中隐藏此属性,同时
Jackson
应该能够对其进行反序列化。这是真的吗?我想提供帮助,但您必须给我一个示例,说明您的
POJO
JSON
是什么样子的,并且您必须向我展示您是如何序列化它(使用JSON输出)和反序列化它的。好的例子比1000个单词要好。是的,这正是我想要做的,对不起,我的问题一开始不够清楚。我编辑它是为了反映你的例子。让我们同意这样一个事实:反序列化过程意味着从JSON字符串到Foo实例,序列化过程意味着从Foo实例到JSON字符串。