2012-08-23 145 views
6

使用杰克逊2,我正在寻找一个通用方式将对象序列化为单个值(然后序列化它们回来后填充只有单个字段),而不必重复创建一个JsonSerializer/JsonDeserializer来处理每个案例。 @JsonIdentityInfo注释非常接近,但稍微遗漏了标记,因为据我所知,它总是会首次序列化整个子对象。杰克逊 - 序列化/反序列化属性作为JSON值

这是我想要做的一个例子。鉴于类:

class Customer { 

    Long id = 99; 
    String name = "Joe"; 
    // Lots more properties 
} 

class Order { 
    String orderNum = "11111" 
    @WhateverAnnotationsINeedHereToDoWhatIWant 
    Customer customer; 
} 

我想为了序列,作为(或者是完全可以接受的我):

{"orderNum":"11111", "customer":"99"} 
{"orderNum":"11111", "customer":{"id":99}} 

@JsonIdentityInfo做些什么使得它处理客户端上更加困难(我们可以假设客户知道如何将客户ID映射回完整的客户信息)。

@JsonIgnoreProperties也可能会显示第二个JSON非常接近,但意味着我将不得不选择退出所有内容但我想要的。

当我反序列化回来时,我只希望客户只用“id”字段进行初始化。

任何奇怪的方式来做到这一点,我失踪了,而没有进入杰克逊soupy内部?据我所知,JsonDeserializer/JsonSerializer没有关于父母的上下文信息,所以似乎没有一种简单的方法来创建一个@JsonValueFromProperty(“id”)类型的Jackson Mix-in,然后只需查看该注释自定义串行器/解串器。

任何想法将不胜感激。谢谢!

回答

8

我曾经需要对不同类型的请求返回的JSON进行精细控制,恐怕我最终会使用自定义序列化器和反序列化器。

一个简单的替代方法是增加@JsonIgnore到订单的客户领域,并添加以下吸气订购:

@JsonProperty("customer") 
public Long getCustomerId(){ 
    if (customer != null){ 
    return customer.getId(); 
    } 
    else { 
    return null; 
    } 
} 

返回然后JSON是:

{"orderNum":"11111", "customer":"99"} 
+0

感谢集成东西!这个简单的解决方案实际上对我来说似乎非常可行,而且现在看起来非常明显;)。在没有@JsonIgnorePropertiesExcept(“id”)注释的情况下,我认为这样做会很好。 – jonc

4

的另一种可能使用@JsonValue,用于id字段。

Jackson 2.1将添加一个功能强制甚至强制引用的序列化为id(由新属性“firstAsId”为@JsonIdentityInfo)。对于所有情况,这可能不适用于反序列化,但可能适用于您。

+0

感谢StaxMan。不幸的是,@JsonValue并不能真正解决这个问题,因为如果我只是自己序列化客户,那么我会期望记录被完全序列化。 – jonc

+1

好的。那么你最好的选择是杰克逊2.1 - 它将允许从类型的序列化中分离引用(总是使用id)。 – StaxMan

+4

最后为了试用2.1版本,因为它在10月份发布了:)。@JsonIdentityReference(alwaysAsId = true)和@JsonIdentityInfo(generator =“generator = ObjectIdGenerators.PropertyGenerator.class”)在序列化结束时效果很好,但在反序列化时不太好,因为它无法解析对象ID引用。它可以与JPA提供者一起实例化一个空对象并仅设置ID进行反序列化,但不确定如何强制jackson解串器执行此操作,而无需为每种可能的引用类型定义自定义解串器 – jonc