【问题标题】:Jackson/Hibernate, meta get methods and serializationJackson/Hibernate,元获取方法和序列化
【发布时间】:2019-08-18 09:57:22
【问题描述】:

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

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

我们面临的挑战如下

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

  2. 实用程序或元方法。 Jackson 似乎是通过 getter 方法而不是字段。一些方法是不与任何列关联的“元”方法。示例 getTotal 方法可以是几个实际字段的值的总和,而没有实际的总字段。其他情况类似,例如 getIncomeAccounts,它根据某些条件过滤帐户。

我写的杰克逊过滤器有点帮助 - 它根据杰克逊属性名称检查类字段是否存在。它还会检查是否存在诸如 JoinColumn 注释之类的注释,以避免字段存在时的递归。

有什么方法可以从休眠中获取元数据并在我的过滤器中使用它?基本上对于给定的实体对象,我有兴趣知道 Jackson 想要序列化的属性是否将映射到列并仅在存在与其关联的列值时进行序列化。 Hibernate 肯定知道属性和列映射。

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

【问题讨论】:

  • 一种解决方法是创建一个重复的类,仅用于序列化,仅包含所需的字段,例如使用反射将所有内容从实体复制到 dto
  • 以下答案有用吗?

标签: java json hibernate jackson jackson-databind


【解决方案1】:

我通常会手动将实体映射到DTO,或者借助MapStruct等工具。
不幸的是,这将为您提供最大的灵活性,但在开始时会产生一些开销。
然而,随着时间的推移,你会发现这是值得的。

Jackson、GSON 和其他序列化工具在开箱即用方面显然受到限制,而且这种自定义需要做的工作量太大,恕我直言,同时也难以理解和维护。

保持简单。

【讨论】:

    【解决方案2】:

    如果您不想在REST API 层上创建新的POJO 模型来表示JSON,则需要在传递到Jackson 层之前准备ORM 模型。

    启用 HibernateXModule

    您应该从启用最适合您的Hibernate 版本的Hibernate module 开始。它解决了lazy-loadings 和内部数据类型的许多问题。

    双向关系

    Read about options 其中Jackson 用于解决序列化期间的循环问题。主要注解有:

    定义适当的可见性

    您可以在ObjectMapperhow to specify jackson to only use fields - preferably globally 上定义全局可见性,并在需要时使用JsonAutoDetect 注释对给定类进行自定义。

    查看POJO型号

    可能在大多数情况下,您将能够重用为ORM 创建的POJO 模型。如果使用注释自定义 JSON 输出会很困难,您始终可以创建自定义类并在额外的映射/业务层中手动将 ORM 模型映射到该模型。

    自定义序列化程序

    如果您需要以一般方式处理某些自定义注释或某些字段,您可以使用BeanSerializerModifierBeanPropertyWriter。这并不容易实现,但它非常强大。在此处查看示例用法:Jackson custom serialization and deserialization

    如何实现双向关系和可见性配置的简单示例:

    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 {
    
        public static void main(String[] args) throws Exception {
            File jsonFile = new File("./resource/test.json").getAbsoluteFile();
    
            Item item0 = new Item();
            item0.setId(1);
            item0.setItemName("Item 0");
    
            Item item1 = new Item();
            item1.setId(2);
            item1.setItemName("Item 1");
    
            List<Item> items = Arrays.asList(item0, item1);
            User user = new User();
            user.setId(123);
            user.setName("Rick");
            user.setUserItems(items);
            items.forEach(item -> item.setOwner(user));
    
            ObjectMapper mapper = new ObjectMapper();
            mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
                    .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                    .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                    .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                    .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
    
            System.out.println(mapper.writeValueAsString(user));
        }
    }
    
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
    class User {
    
        private int id;
        private String name;
        private List<Item> userItems;
    
        // getters, setters
    }
    
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
    class Item {
    
        private int id;
        private String itemName;
        private User owner;
    
        // getters, setters
    }
    

    上面的代码打印:

    {"id":123,"name":"Rick","userItems":[{"id":1,"itemName":"Item 0","owner":123},{"id":2,"itemName":"Item 1","owner":123}]}
    

    【讨论】:

      猜你喜欢
      • 2016-10-07
      • 2017-09-29
      • 1970-01-01
      • 1970-01-01
      • 2014-07-23
      • 1970-01-01
      • 1970-01-01
      • 2016-12-11
      • 1970-01-01
      相关资源
      最近更新 更多