杰克逊反序列化:如何引用另一个属性?

时间:2014-12-24 16:40:58

标签: java json jackson

鉴于此示例文档:

{
    "currency": "USD",
    "items": [{
        "description": "foo",
        "price": 100
    }, {
        "description": "bar",
        "price": 50
    }]
}

这些Java类

class Order {

  Currency currency;

  List<Item> items;

  static class Item {

    String description;

    Money price;

  }

  static class Money {

    BigDecimal amount;

    @SomeDeserializationAnnotation("to reference currency from parent document Order")
    Currency currency

  }

}

是否存在类似@SomeDeserializationAnnotation("to reference currency from parent document Order")的内容?

如果没有,是否可以使用自定义反序列化器?

1 个答案:

答案 0 :(得分:1)

首先,@ JsonManagedReference和@JsonBackReference在这里不起作用,因为: 带注释的属性可以是bean,数组,Collection(List,Set)或Map类型,它必须是bean属性(由使用BeanSerializer序列化的类型的属性处理

货币字段是简单的字符串,默认情况下使用&#39; FromStringDeserializer&#39; (不是BeanDeserializer)。

您可以使用Order类的自定义反序列化器来解决您的问题,该类会转换值并使用注入值来转换子对象:

@JsonDeserialize(using = OrderDeserializer.class)
class Order {
    Currency currency;
    List<Item> items;
}

class Item {
    String description;
    Money price;
}

class Money {
    BigDecimal amount;
    Currency currency;

    public Money(BigDecimal amount, @JacksonInject Currency currency) {
        this.amount = amount;
        this.currency = currency;
    }

}

class OrderDeserializer extends JsonDeserializer<Order> {

    @Override
    public Order deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectMapper objectCodec = (ObjectMapper)ctxt.getParser().getCodec();

        JavaType listType = ctxt.getTypeFactory().constructCollectionType(List.class, Item.class);

        JsonNode jsonNode = jp.readValueAsTree();
        JsonNode currencyNode = jsonNode.get("currency");
        JsonNode itemsNode = jsonNode.get("items");

        Currency currency = objectCodec.treeToValue(currencyNode, Currency.class);

        InjectableValues values = new InjectableValues.Std().addValue(Currency.class, currency);
        List<Item> items = objectCodec.reader(listType).with(values).readValue(itemsNode);

        return new Order(currency, items);
    }
}

这里最大的缺点是,如果添加/删除/更新Order类,则需要更新反序列化器实现。