简体   繁体   English

我如何强迫杰克逊使用对象的定位器?

[英]How do I force Jackson to use an Object's Setters?

Given I have the following JSON file: 鉴于我有以下JSON文件:

{
    "cleanup": false,
    "clearCache": false
}

and the following bean: 和以下bean:

import org.apache.commons.lang3.Validate;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Config implements IHoldConfiguration {

    public static final boolean DEFAULT_CLEANUP = false;
    public static final boolean DEFAULT_CLEAR_CACHE = false;
    public static final int DEFAULT_CONCURRENCY = 1;

    @JsonProperty(value = "cleanup", required = false, defaultValue = "false")
    private Boolean cleanup;

    @JsonProperty(value = "clearCache", required = false, defaultValue = "false")
    private Boolean clearCache;

    @JsonProperty(value = "concurrency", required = false, defaultValue = "1")
    private Integer concurrency;

    public boolean isCleanup() {
        return this.cleanup.booleanValue();
    }

    public void setCleanup(final Boolean cleanup) {
        this.cleanup = cleanup != null ? cleanup : DEFAULT_CLEANUP;
    }

    public boolean isClearCache() {
        return this.clearCache.booleanValue();
    }

    public void setClearCache(final Boolean clearCache) {
        this.clearCache = clearCache != null ? clearCache : DEFAULT_CLEAR_CACHE;
    }

    public int getConcurrency() {
        return this.concurrency.intValue();
    }

    public void setConcurrency(Integer concurrency) {

        if (concurrency == null) {
            concurrency = DEFAULT_CONCURRENCY;
        } else {
            Validate.inclusiveBetween(1, Integer.MAX_VALUE, concurrency,
                    String.format("concurrency must be in range [1, %s]", Integer.MAX_VALUE));
        }

        this.concurrency = concurrency;
    }
}

How do I force Jackson 2.9.2 to use my concurrency setter? 如何强制Jackson 2.9.2使用我的concurrency设置器? Currently, when deserialized from JSON to bean, using new ObjectMapper().readValue(inputStream, Config.class) , concurrency is set to null . 目前,当从JSON反序列化为bean时,使用new ObjectMapper().readValue(inputStream, Config.class)concurrency性设置为null

I thought that Jackson used the setters in a bean, if provided, to set a property. 我认为杰克逊在豆子中使用了固定器(如果提供的话)来设置属性。 After seeing the deserialized result, and debugging, I've found this is not true. 在看到反序列化的结果和调试之后,我发现这不是真的。 Since the defaultValue aatribute of JsonProperty is for documentation only, I thought I could add default value setting in the setters, but obviously this did not work. 由于defaultValue的aatribute JsonProperty仅用于文档,我想我可以在setter方法添加默认值设置,但显然这并不工作。 How can I accomplish this? 我怎么能做到这一点?

The problem is that since concurrency is not declared in your json string the setter isn't being called. 问题是,由于未在json字符串中声明并发性,因此未调用setter。 If you had 如果你有

{
    cleanup: false,
    clearCache: false,
    concurrency: null
}

Then the setter would be called with a null argument and you set your default value. 然后使用null参数调用setter并设置默认值。

To get a default without tweaking the json string you could do a couple of things. 要在不调整json字符串的情况下获取默认值,您可以执行以下操作。 Firstly you can simply set the default on the variable when it is declared: 首先,您可以在声明变量时简单地设置变量的默认值:

public class Config implements IHoldConfiguration {
    ...
    public static final int DEFAULT_CONCURRENCY = 1;

    ...
    private Integer concurrency = Integer.valueOf(DEFAULT_CONCURRENCY);

Now it doesn't matter that Jackson doesn't try to set concurrency because it will already be constructed with the correct value. 现在,杰克逊没有尝试设置并发性并不重要,因为它已经构建了正确的值。 Alternatively you could force Jackson to use a constructor and it will pass all the values even those that are not in the json string. 或者,您可以强制Jackson使用构造函数,它将传递所有值,即使是那些不在json字符串中的值。

So for example you could add a constructor like: 例如,您可以添加如下构造函数:

@JsonCreator
public Config (@JsonProperty("cleanup") Boolean cleanup,
               @JsonProperty("clearCache") Boolean clearCache,
               @JsonProperty("concurrency") Integer concurrency) {
    ....

And put your logic in there. 把你的逻辑放在那里。

You can not force it to be called because there is nothing to call it with. 你不能强迫它被调用,因为没有什么可以调用它。

The usual way to set defaults is to either directly assign value to field in declaration, like: 设置默认值的常用方法是直接为声明中的字段赋值,例如:

private Integer concurrency = Integer.valueOf(1);

or do this in default constructor. 或者在默认构造函数中执行此操作。

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

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