使用Jackson将JPA实体序列化为JSON

5

关于Jackson/JPA组合的问题

  1. 如果当前应用程序中有大约20个实体,并且我已经在POM中添加了Jackson依赖项,这是否意味着所有实体默认准备好转换为JSON对象?我看到一个示例项目似乎只有标记为@JsonIgnored的类被JSON跳过。如果是这样,那么这是如何发生的,背后有什么机制?没有任何Jackson注释的实体如何处理,默认忽略还是不忽略?我一直在网上寻找资源,但没什么运气。

  2. 如果只有20个实体中的一个需要映射到JSON对象,那么这是否意味着我必须将@JsonIgnore添加到其他19个实体中?如果不是,Jackson如何区分要处理的实体?

谢谢。


在你的上下文中,“实体”是什么意思?是一个类吗?还是类的字段?或者是方法?如果你表述含糊不清,我无法帮助你...... - Pascal Gélinas
@pgelinas 这是一个类,就像 JPA 实体类一样。 - Dreamer
2个回答

15

Jackson和JPA之间没有任何关系。Jackson是一个JSON解析库,而JPA是一个持久化框架。Jackson可以对几乎任何对象进行序列化,唯一的要求是该对象具有可识别的属性(Javabean类型的属性或使用@JsonProperty注释的裸露字段)。对于反序列化,还需要目标类型具有默认(无参)构造函数。因此,例如,这是Jackson可以序列化的对象:

// Class with a single Javabean property, "name"
class Person {
    private String name;

    public String getName() { return name ; }
    public String setName(String name) { this.name = name ; }
}

这里还有另一个:

// Class with a single field annotated with @JsonProperty
class Account {
    @JsonProperty("accountNumber")
    private String accountNumber;
}

这里又有一个:

@Entity
public class User {
    @Id
    private Long id;

    @Basic
    private String userName;

    @Basic
    @JsonIgnore
    private String password;

    @Basic
    @JsonIgnore
    private Address address;

    // Constructors, getters, setters
}

最后一个例子展示了一个JPA实体类 - 就Jackson而言,它可以像其他任何类型一样被序列化。但请注意其字段:当该对象序列化为JSON时,其中的两个字段不会被包含 - "password"和"address"。这是因为它们已经使用@JsonIgnore进行了注释。 @JsonIgnore注解允许开发人员说“嘿,序列化这个对象没问题,但在这样做时,请不要将这些字段包含在输出中”。此排除仅针对此对象的字段,因此例如,如果您在另一个类中包含了一个Address字段,但没有将该字段标记为可忽略,则该字段将被序列化。

为了在所有情况下防止类型序列化,无论上下文如何,使用@JsonIgnoreType注解。当用于类型时,它基本上意味着“我不关心此类型在哪里使用,永远不要序列化它”。


非常好的解释。谢谢你。还有一个问题,JACKSON是否默认自动将所有JPA实体转换为JSON对象,即使没有显式声明(如果不使用@JsonIgnore@JsonIgnoreType)?如果是这样,那么这种冗余是什么意思?我知道所有JPA实体都是可序列化的,即使没有JACKSON,但这是否意味着将所有实体转换为JSON对象没有额外的成本? - Dreamer
2
Jackson 在未触发序列化之前不会做任何事情,例如通过调用 new ObjectMapper().writeValueToString(new Person();。在此情况下,Person 对象将被写成 JSON 格式,同时也包括它所引用的对象(作为类变量)。在写出这些对象为 JSON 时,Jackson 将忽略带有 @JsonIgnore 注解的字段或带有 @JsonIgnoreType 注解的类型。这就是规则。Jackson 没有说过“噢,这个包中有 50 个类,让我们把它们转换成 JSON”。希望这能澄清一些问题。 - Perception
那么JACKSON不会一次性将它们全部转换,而是对于一个实体(比如ClassNoJSON),当它被管理时,ObjectMapper才开始工作?换句话说,开发人员应该小心并且应该在不必要的实体或字段上放置@JsonIgnoreType@JsonIgnore以获得更好的性能?我只是想澄清一下,我正在为一个实体添加JSON功能,但不会在所有实体上增加额外的成本。 - Dreamer
1
@Dreamer - 是的,那基本上是正确的。Jackson 不会以任何方式预处理类,因此从类中添加或省略 Jackson 注释只控制运行时发生的事情。使用 @JsonIgnore@JsonIgnoreType 可以减少需要为某个调用序列化的字段/类型的总数,这可能会在许多情况下导致性能(内存和速度)的提高。 - Perception

1
不,你不需要在每个类上添加@JsonIgnore,如果你尝试了会得到一个编译错误,因为你不能把它放在那里。Jackson只会处理你给它的对象,这不是魔法。
Jackson文档很容易在网上找到,比如在github上的项目页面或者在codehaus website上。

Jackson 只会处理你给予它的对象,它并不具有魔力。您能否更具体地说明如何“给予它”?感谢链接,但我在 JACKSON DOCUMENTATION 中没有找到太多关于 JPA/Jackson 的资料。 - Dreamer
嗯,那你的问题是关于什么的呢?如何配置JPA(hibernate?)使用Jackson进行序列化? - Pascal Gélinas
是的,问题更像是如何在JPA上配置Jackson,但我的困惑实际上是关于JACKSON如何处理那些没有任何Jackson注释的实体,默认情况下是否被忽略? - Dreamer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接