反序列化时忽略属性

时间:2013-04-15 16:08:22

标签: java json jackson

我有一个简单的界面,其中包含属性的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我们打算跟踪这个属性,当money属性被发送到服务器并且Jackson试图反序列化它时,这似乎会使应用程序崩溃up MalformedJsonException:无法构造Money类型的对象。

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

5 个答案:

答案 0 :(得分:31)

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

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

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

答案 1 :(得分:18)

好的,所以@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

答案 2 :(得分:2)

如果您不拥有或无法通过添加@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);

答案 3 :(得分:0)

使用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
   }

}

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

答案 4 :(得分:0)

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

史前史: 在我的项目中,有一个将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;
       }
    }
});