47

我有一个简单的接口,带有属性的 getter 和 setter。

public interface HasMoney { 

      Money getMoney();

      void setMoney(Money money);

 }

我有另一个类 UserAccount 实现了这个接口。

public class UserAccount implements HasMoney {

       private Money money;

       @Override
       Money getMoney() // fill in the blanks

       @Override
       void setMoney(Money money) // fill in the blanks

}

我的问题是我想序列化money 属性,但在反序列化时忽略它,即不接受来自用户的该属性的任何值。我已经在 setter 上尝试了 @JsonIgnore ,在 getter 上尝试了 @JsonIgnore(false) ,它确实忽略了它,但它在序列化它的同时也这样做了。

我在 setter 上尝试了@JsonIgnore,在 getter 上尝试了@JsonProperty,只是为了明确告诉 Jackson 我们打算跟踪这个属性,当金钱属性发送到服务器并且 Jackson 试图反序列化它并抛出 MalformedJsonException 时,这似乎会使应用程序崩溃:无法构造 Money 类型的对象。

最奇怪的是,将@JsonIgnore 放在setter 上,将@JsonProperty 放在setter 上适用于大多数情况下属性是原始的情况。

4

5 回答 5

60

版本 2.6.0+ 允许在类级别使用 @JsonIgnoreProperties 完成此操作。

@JsonIgnoreProperties(value={ "money" }, allowGetters=true)

看看这个已关闭的问题: https ://github.com/FasterXML/jackson-databind/issues/95

于 2016-09-16T05:55:23.963 回答
29

好的,所以@JsonIgnore 的行为从 1.9 开始发生了根本性的变化(更糟糕的是 imo)。无需详细说明为什么您的属性在反序列化期间没有被忽略,请尝试以下代码来修复它:

public class UserAccount implements HasMoney {
    @JsonIgnore
    private BigDecimal money;

    // Other variable declarations, constructors

    @Override
    @JsonProperty
    public BigDecimal getMoney() {
        return money;
    }

    @JsonIgnore
    @Override
    public void setMoney(final BigDecimal money) {
        this.money = money;
    }

    // Other getters/setters
}

注意现场使用@JsonIgnore- 它是工作解决方案所必需的。

注意:根据您的环境和用例,您可能需要对 ObjectMapper 实例进行额外配置,例如USE_GETTERS_AS_SETTERS、AUTO_DETECT_GETTERS、AUTO_DETECT_SETTERS

于 2013-04-15T23:12:26.970 回答
6

如果您不拥有或无法通过添加注释来更改类,您将在您的实现中@JsonIgnore使用从2.5版开始的 mixin 来获得预期的结果。

public abstract class HasMoneyMixin {
    @JsonIgnore
    public abstract Money getMoney();
}

配置映射器以使用 mixin,

ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(HasMoney.class, HasMoneyMixin.class);
// avoid failing if all properties are empty
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
于 2018-11-03T11:04:59.273 回答
3

使用 Jackson 2.10,您可以实现如下所示的只读字段:

一个真实的领域

public class UserAccount implements HasMoney {

   @JsonProperty(access = JsonProperty.Access.READ_ONLY)
   private Money money;
   
   // getter and setter

}

虚拟场

@JsonIgnoreProperties(ignoreUnknown = true) // to ignore ALL unknown properties
// OR
@JsonIgnoreProperties(value = {"money"}, allowGetters = true) // to ignore only 'money' input
public class UserAccount implements HasMoney {

   @JsonProperty
   public Money getMoney() {
       // some calculation
   }

}

该值将被序列化,但在反序列化期间被忽略。

于 2020-10-06T06:57:08.343 回答
3

显然我的解决方案迟到了,但肯定会对其他人有所帮助。

Prehistory:在我的项目中,有一个类将 JSON 字符串直接读取到实体中。JSON 包含一个不是类变量的属性。因为

objectMapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

在反序列化期间不会创建实体的实例(在我们的项目中需要这种情况下的异常)。

解决方案

objectMapper.addHandler(new DeserializationProblemHandler() {
    @Override
    public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer<?> deserializer, Object beanOrClass, String propertyName) throws IOException {
       if( (propertyName.equals("propertyToBeIgnored") && beanOrClass.getClass().equals(ClassOfTheProperty.class)) {
           p.skipChildren();
           return true;
       } else {
           return false;
       }
    }
});
于 2020-12-16T18:36:23.160 回答