如何仅序列化 Jackson 的孩子的 ID

Posted

技术标签:

【中文标题】如何仅序列化 Jackson 的孩子的 ID【英文标题】:How to serialize only the ID of a child with Jackson 【发布时间】:2013-07-06 16:57:12 【问题描述】:

在使用 Jackson (fasterxml.jackson 2.1.1) 时,是否有一种仅序列化孩子 id 的内置方法?我们想通过 REST 发送一个 Order,它有一个 Person 引用。但是 person 对象非常复杂,我们可以在服务器端刷新它,所以我们只需要主键。

或者我需要一个自定义序列化器吗?还是我需要@JsonIgnore 所有其他属性?在请求Order 对象时,这会阻止Person 数据被发回吗?我还不确定我是否需要它,但如果可能的话,我想控制它......

【问题讨论】:

这有帮助吗? ***.com/questions/8179986/… 【参考方案1】:

有几种方法。第一个是使用@JsonIgnoreProperties 来删除孩子的属性,如下所示:

public class Parent 
   @JsonIgnoreProperties("name", "description" ) // leave "id" and whatever child has
   public Child child; // or use for getter or setter

另一种可能性,如果子对象总是序列化为 id:

public class Child 
    // use value of this property _instead_ of object
    @JsonValue
    public int id;

另外一种方法是使用@JsonIdentityInfo

public class Parent 
   @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
   @JsonIdentityReference(alwaysAsId=true) // otherwise first ref as POJO, others as id
   public Child child; // or use for getter or setter

   // if using 'PropertyGenerator', need to have id as property -- not the only choice
   public int id;

这也适用于序列化,并忽略 id 以外的属性。但是,结果不会被包装为 Object。

【讨论】:

这真的很有用。谢谢。当您使用@JsonIdentityReference(alwaysAsId=true) 时,Jackson 无法将其反序列化,对吧?是否可以通过编写自定义的 Serializer/Deserializer 来实现相同的功能? 正确 -- 如果没有对象 id 可以匹配,Jackson 无法判断;所以通常这个选项对于仅序列化的用例是有意义的(如果需要,其他东西可以将它拼凑在一起)。自定义(反)序列化器可以做任何你想做的事情,所以理论上是的。 @StaxMan 你能告诉我如何使用 '@JsonIdentityReference(alwaysAsId=true' 但我想让 Result 包装在 Object 中而不是作为普通属性。 @Andrew 不太清楚你的意思。如果孩子是List 或 POJO,基本无知并不关心。但是如果你的意思是申请List内的内容,此时不能这样做;你需要一个包装器对象。 最后一种方法将第一次出现为字符串"id1",然后将下一个作为引用*id1。如何让它始终作为字符串?【参考方案2】:

您可以像这样编写自定义序列化程序:

public class ChildAsIdOnlySerializer extends StdSerializer<Child> 

  // must have empty constructor
  public ChildAsIdOnlySerializer() 
    this(null);
  

  public ChildAsIdOnlySerializer(Class<Child> t) 
    super(t);
  

  @Override
  public void serialize(Child value, JsonGenerator gen, SerializerProvider provider)
      throws IOException 
    gen.writeString(value.id);
  

然后通过使用@JsonSerialize注释字段来使用它:

public class Parent 
   @JsonSerialize(using = ChildAsIdOnlySerializer.class)
   public Child child;


public class Child 
    public int id;

【讨论】:

【参考方案3】:

例如,给定一个具有员工结构的简单公司,结合

@JsonIgnore
@ManyToOne(cascade = CascadeType.REFRESH, CascadeType.DETACH)
@JoinColumn(name = "child_id")

我建议添加以下内容:

@JsonProperty("child_id") 如果没有它,将 child_id 作为属性发送,您将不会在客户端得到任何东西,并且- @JsonIgnoreProperties 它将提供复制和粘贴从服务器接收到的 Json 并将其发回以进行更新的选项。如果没有它,您将在发回时收到异常,或者您必须从收到的 Json 中删除 child_id 属性。

public class Company 
@OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
    private List<Employee> employees;


@JsonIgnoreProperties(value = "company_id",allowGetters = true)
public class Employee
    @JsonIgnore
    @ManyToOne(cascade = CascadeType.REFRESH, CascadeType.DETACH)
    @JoinColumn(name = "company_id")   
    public Company company

   @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, 
     property="id")
   @JsonIdentityReference(alwaysAsId=true) 
   @JsonProperty("company_id")
   
   public Company getCompany() 
        return company;
    

【讨论】:

以上是关于如何仅序列化 Jackson 的孩子的 ID的主要内容,如果未能解决你的问题,请参考以下文章

Spring Jackson反序列化只选择数组的第一项

如何在 Jackson 中使用自定义序列化程序?

如何使用 Jackson 反序列化来自 json 对象的对象数组

等效于@JsonIgnore,但仅适用于使用 Jackson 的 xml 字段/属性转换

Jackson - 如何处理(反序列化)嵌套的 JSON?

Jackson 未对 JPA id 字段进行序列化