繁体   English   中英

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

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

我想进一步探讨这个问题 ,我一直在漫游一个小时,但没有发现任何问题。

基本上,我想做的是在反序列化期间具有通过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;
    }
}

如您所见,更糟的是,该属性是最终属性(这就是为什么我热衷于在通过反序列化对Foo实例化时使用Jackson反射功能)。 我已经阅读了有关以不同方式对setter和getter进行注释的潜在解决方案,但我希望尽可能保留此属性的最终状态。 如果不可能的话 ,我会选择非最终财产。

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

我也在github上阅读了该线程,但是目前尚未实际实现任何建议的实现方式。

谢谢


编辑:使事情更清楚

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
}

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

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

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

{"bar":"Value"}
Value

编辑1


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

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 2.6开始,可以将属性标记为只读或只写。 这比修改两个访问器上的注释(对于非最终字段)更简单,并将所有信息都保存在一个地方。 重要的是要注意,Jackson默认认为final字段可写的。

但是,对于最后一个字段而言,允许反序列化是不够的,因为您不能在该字段上使用setter:它需要通过构造函数直接或使用生成器或可以由Jackson进行反序列化的另一种类型进行设置。 当使用带有属性作为参数的构造函数时,需要使用@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