Jackson/Hibernate,meta get 方法和序列化

我们有很多具有嵌套关系的休眠实体类。我试图找到将给定实体转换为等效json格式的最佳方法。

我知道JsonIgnore,Jackson mixins和JsonFilters,并且一直在尝试这些。

我们面临的挑战如下

  1. 使用 OneToMany/JoinColumn 或类似注释相互关联的对象 - 创建无限递归。

  2. 实用工具或元方法。杰克逊似乎在通过获取方法而不是通过字段。某些方法是不与任何列关联的“meta”方法。示例 getTotal 方法可以对几个实际字段的值求和,而没有实际的总计字段。其他情况类似,例如getIncomeAccounts,它根据某些标准过滤帐户。

我写的 Jackson Filter 有点帮助 - 它根据 Jackson 属性名称检查类字段是否存在。它还会检查是否存在诸如 JoinColumn 批注之类的批注,以避免在字段存在时递归。

有没有办法从休眠中获取元数据并在我的过滤器中使用它?基本上,对于给定的实体对象,我有兴趣知道Jackson想要序列化的属性是否会映射到列,并且只有在存在与其关联的列值时才进行序列化。Hibernate 当然知道属性和列映射。

Mixins和jsonignore选项是可行的,但是我们依赖于个人开发人员记住将注释放在适当的位置。通常,当我们真的想要获取导出的数据来分析一些问题并在本地创建测试用例时,忘记的注释被发现得太晚了。


哆啦的时光机
浏览 161回答 2
2回答

红颜莎娜

我通常做的是手动将实体映射到DTO,或者在MapStruct等工具的帮助下。不幸的是,这将为您提供最大的灵活性,在开始时会有一些开销。然而,随着时间的推移,你会发现这是值得的。Jackson、GSON 和其他序列化工具在开箱即用的功能方面显然受到限制,而且这种自定义需要太多的工作,恕我直言,同时也难以理解和维护。保持简单。

繁星点点滴滴

如果不想创建新模型以在级别上进行表示,则需要在传递到层之前准备模型。POJOJSONREST APIORMJackson启用休眠X模块您应该从启用最适合您的版本的Hibernate模块开始。它解决了许多内部数据类型问题。Hibernatelazy-loadings双向关系阅读有关在序列化过程中解决周期问题的选项。主要注释包括:JacksonJsonManagedReferenceJsonBackReferenceJsonIdentityInfo定义适当的可见性您可以在 上定义全局可见性,如何指定 jackson 以仅使用字段 - 最好是全局的,如果需要使用&nbsp;JsonAutoDetect&nbsp;注释为给定类自定义它。ObjectMapper查看模型POJO可能在大多数情况下,您将能够重用为 创建的模型。如果使用注释自定义输出非常困难,您可以随时在额外的映射/业务层中手动创建自定义类并将模型映射到此类和模型。POJOORMJSONORM自定义序列化器如果您需要以一般方式处理某些自定义注释或某些字段,则可以使用BeanSerializerModifier和BeanPropertyWriter。它不容易实现,但它非常强大。请参阅此处的示例用法:Jackson 自定义序列化和反序列化。如何为双向关系和可见性配置完成的简单示例:import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.JsonIdentityInfo;import com.fasterxml.jackson.annotation.ObjectIdGenerators;import com.fasterxml.jackson.databind.ObjectMapper;import java.io.File;import java.util.Arrays;import java.util.List;public class JsonApp {&nbsp; &nbsp; public static void main(String[] args) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; File jsonFile = new File("./resource/test.json").getAbsoluteFile();&nbsp; &nbsp; &nbsp; &nbsp; Item item0 = new Item();&nbsp; &nbsp; &nbsp; &nbsp; item0.setId(1);&nbsp; &nbsp; &nbsp; &nbsp; item0.setItemName("Item 0");&nbsp; &nbsp; &nbsp; &nbsp; Item item1 = new Item();&nbsp; &nbsp; &nbsp; &nbsp; item1.setId(2);&nbsp; &nbsp; &nbsp; &nbsp; item1.setItemName("Item 1");&nbsp; &nbsp; &nbsp; &nbsp; List<Item> items = Arrays.asList(item0, item1);&nbsp; &nbsp; &nbsp; &nbsp; User user = new User();&nbsp; &nbsp; &nbsp; &nbsp; user.setId(123);&nbsp; &nbsp; &nbsp; &nbsp; user.setName("Rick");&nbsp; &nbsp; &nbsp; &nbsp; user.setUserItems(items);&nbsp; &nbsp; &nbsp; &nbsp; items.forEach(item -> item.setOwner(user));&nbsp; &nbsp; &nbsp; &nbsp; ObjectMapper mapper = new ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .withFieldVisibility(JsonAutoDetect.Visibility.ANY)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .withGetterVisibility(JsonAutoDetect.Visibility.NONE)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .withSetterVisibility(JsonAutoDetect.Visibility.NONE)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(mapper.writeValueAsString(user));&nbsp; &nbsp; }}@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")class User {&nbsp; &nbsp; private int id;&nbsp; &nbsp; private String name;&nbsp; &nbsp; private List<Item> userItems;&nbsp; &nbsp; // getters, setters}@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")class Item {&nbsp; &nbsp; private int id;&nbsp; &nbsp; private String itemName;&nbsp; &nbsp; private User owner;&nbsp; &nbsp; // getters, setters}以上代码打印:{"id":123,"name":"Rick","userItems":[{"id":1,"itemName":"Item 0","owner":123},{"id":2,"itemName":"Item 1","owner":123}]}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java