反序列化时忽略属性

Nis*_*ani 29 java json jackson

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

public interface HasMoney { 

      Money getMoney();

      void setMoney(Money money);

 }
Run Code Online (Sandbox Code Playgroud)

我有另一个类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

}
Run Code Online (Sandbox Code Playgroud)

我的问题是我想序列化money属性但在反序列化时忽略它,即不接受用户对此属性的任何值.我在setter上尝试了@JsonIgnore,在getter上尝试了@JsonIgnore(false),它确实忽略了它,但它也是在序列化时也是如此.

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

最奇怪的是,当属性是原始的时,将@JsonIgnore放在setter上并且setter上的@JsonProperty适用于大多数情况.

kme*_*mek 35

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

@JsonIgnoreProperties(value={ "money" }, allowGetters=true)
Run Code Online (Sandbox Code Playgroud)

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

  • 这个解决方案更清洁 (3认同)
  • 这也适用于不可变的 kotlin 数据类。 (2认同)

Per*_*ion 21

好的,所以@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
}
Run Code Online (Sandbox Code Playgroud)

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

注意:根据您的环境和用例,您可能需要在ObjectMapper实例上进行其他配置,例如, USE_GETTERS_AS_SETTERS,AUTO_DETECT_GETTERS,AUTO_DETECT_SETTERS .


Ser*_*nov 12

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

一个真实的领域

public class UserAccount implements HasMoney {

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

}
Run Code Online (Sandbox Code Playgroud)

虚拟场

@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
   }

}
Run Code Online (Sandbox Code Playgroud)

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


Ruw*_*han 5

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

public abstract class HasMoneyMixin {
    @JsonIgnore
    public abstract Money getMoney();
}
Run Code Online (Sandbox Code Playgroud)

配置映射器以使用 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);
Run Code Online (Sandbox Code Playgroud)


小智 5

显然我的解决方案已经晚了,但肯定会对其他人有帮助。

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

objectMapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
Run Code Online (Sandbox Code Playgroud)

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

解决方案

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;
       }
    }
});
Run Code Online (Sandbox Code Playgroud)