【问题标题】:JAVA JACKSON: serialize a class with two field instead of all classJAVA JACKSON:用两个字段而不是所有类序列化一个类
【发布时间】:2016-04-18 18:36:31
【问题描述】:

当它被外键调用时,我需要序列化一个只有两列的实体。我在 Wildfly 工作,所以我正在寻找杰克逊的解决方案。

假设我有实体类 A

public class A{
   private Long id;
   private String name;
   private String anotherinfo;
   private String foo;
   ...
}

和另一个 B 类:

public class B{
   private Long id;
   private String name;
   private A parent;
}

当我搜索 A 时,我想用他的所有字段序列化 A,但是当我需要检索 B 的一个 istance 时,我只需要两个字段(一个 ID 和一个标签)

如果我使用注释:

@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
@JsonIdentityReference(alwaysAsId=true)
private A parent;

我将只返回 id。

我想要的结果是:

B: {
  "id" : 1,
  "name" : "test",
  "parent" : {
     "id" : 1,
     "name" : 2
  }
}

【问题讨论】:

  • 对字段使用关键字transient,它们不会被序列化。
  • transient 关键字在这里可能会有所帮助。
  • @LearningPhase 例如,如果您在“anotherinfo”上使用 Transient,则该字段将永远不会被序列化。当我要求对象 A 时,我需要另一个信息

标签: java json serialization jackson


【解决方案1】:

您可以使用JsonIgnoreProperties 注释来禁用特定字段进行序列化(和反序列化):

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

public class B {
    private Long id;
    private String name;

    @JsonIgnoreProperties({"anotherinfo", "foo"})
    private A parent;

【讨论】:

  • 如果被忽略的属性集不随时间变化,这很好。然而,如果人们期望可能有更多的属性需要忽略,这可能是有问题的,因为在 A 中添加一个新字段意味着在其他文件中扩展被忽略的列表。因此,我发现声明要序列化的明确字段列表的解决方案更好。但是再说一遍:如果属性集是固定的,那就没问题了。
【解决方案2】:

A 扩展另一个类,比如C

class C {
   Long id;
   String name;
}

class A extends C {
   String anotherinfo;
   String foo;
   ...
}

然后,在B

class B {
   Long id;
   String name;
   @JsonSerialize(as=C.class)
   A parent;
}

当您序列化B 时,其parent 字段将仅包含来自C 的字段,但在您序列化A 对象的其他任何地方,您将看到来自A 和@987654332 的所有字段@。

欲了解更多信息,请查看https://github.com/FasterXML/jackson-annotations#annotations-for-choosing-moreless-specific-types

【讨论】:

  • 我不能使用这个解决方案,因为我有一个定义明确的继承策略来使用抽象类和标准化方法
  • @DanieleLicitra C 也可以是带有 getProperty() Bean 样式方法的接口,并由 A 实现。(实现的接口没有限制。)所以如果你对 A 有源代码控制,我发现这个解决方案比自定义序列化程序更容易且样板更少。
【解决方案3】:

解决了添加 Json 序列化器的问题。

我已经为父类创建了一个 NationJsonSerializer:

public class NationJsonSerializer extends JsonSerializer<TNation> {

@Override
public void serialize(TNation value, JsonGenerator jgen, SerializerProvider provider) 
  throws IOException, JsonProcessingException {
    jgen.writeStartObject();
    jgen.writeNumberField("id", value.getId());
    jgen.writeStringField("name", value.getComune());
    jgen.writeStringField("iso", value.getCap());
    jgen.writeEndObject();
}
}

然后,在城市类中,我放了注释

@JoinColumn(name = "idtnation",referencedColumnName = "id",nullable = true)
@ManyToOne(targetEntity = TNation.class, fetch = FetchType.EAGER)
@JsonSerialize(using = NationJsonSerializer.class)
private TNation nation;

所以,如果我使用方法 Nation n = getNation(long id);我会收到所有列,但如果我使用 getCity(),我会收到一个简化版本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 2020-09-30
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 2014-10-06
    相关资源
    最近更新 更多