代码之家  ›  专栏  ›  技术社区  ›  Joald

强制属性在Jackson中序列化为标识

  •  1
  • Joald  · 技术社区  · 7 年前

    我和一个班

    (免责声明,我在Kotlin写,但我把它翻译成Java,所以更多的人可以阅读它)

    @JsonIdentityInfo(
        ObjectIdGenerators.PropertyGenerator.class,
        "id"
    )
    public class Foo implements Serializable {
        public int id;
        public List<Foo> fooList;
    }
    

    我要序列化另一个对象,该对象包含 Foo s,但我希望序列中的所有条目 fooList 是ID,不是对象。我们想到的一个解决方案是,在序列化之前,按照拓扑顺序对它们进行排序,因为它们形成了一个有向非循环图。但这显然不是一个完美的解决方案,所以我想知道是否有一个注释或者一个干净的杰克逊方法来做类似的事情。

    编辑:
    包含foo列表的类如下所示:

    public class Bar implements Serializable {
        public List<Foo> fooList;
    }
    

    当我反序列化 Bar 此JSON的实例:

    {
      "fooList": [
        {
          "id": 0,
          "fooList": [1]
        }, 
        {
          "id": 1,
          "fooList": []
        }
      ]
    }
    

    然后我将其序列化,我希望输出与输入相同,但实际上是这样:

    {
      "fooList": [
        {
          "id": 0,
          "fooList": [
            {
              "id": 1,
              "fooList": []
            }
          ]
        },
        1
      ]
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   f-CJ    7 年前

    您可以创建一个扩展自 Foo 为提供可选序列化的类 fooList 使用注释 @JsonGetter 就像包装纸一样。

    班级:

    public class Foo implements Serializable {
        private int id;
        private List<Foo> fooList;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public List<Foo> getFooList() {
            return fooList;
        }
    
        public void setFooList(List<Foo> fooList) {
            this.fooList = fooList;
        }
    }
    

    Bar 班级:

    public class Bar implements Serializable {
        public List<FooJsonSimplifiedSerializationWrapper> fooList;
    
        public List<FooJsonSimplifiedSerializationWrapper> getFooList() {
            return fooList;
        }
    
        public void setFooList(List<FooJsonSimplifiedSerializationWrapper> fooList) {
            this.fooList = fooList;
        }
    }
    

    FooFooJsonSimplifiedSerializationWrapper 用于序列化的包装,它有一个要从中转换的方法 Lst<Foo> 列出; Foofookson简化序列包装器 >在序列化之前,必须在某个时间点调用:

    public class FooJsonSimplifiedSerializationWrapper extends Foo {
        @JsonGetter("fooList")
        public List<Integer> serializeFooList() {
            return this.getFooList().stream().map(f -> f.getId()).collect(Collectors.toList());
        }
    
        public static List<FooJsonSimplifiedSerializationWrapper> convertFromFoo(List<Foo> fooList) {
            return fooList.stream().map(f -> {
                FooJsonSimplifiedSerializationWrapper fooSimplified = new FooJsonSimplifiedSerializationWrapper();
                BeanUtils.copyProperties(f, fooSimplified);
    
                return fooSimplified;
    
            }).collect(Collectors.toList());
        }
    }
    

    Main 通过一些测试:

    public static void main(String[] args) throws IOException {
        Foo foo = new Foo();
        foo.setId(1);
    
        Foo fooChild = new Foo();
        fooChild.setId(2);
        fooChild.setFooList(new ArrayList<>());
    
        Foo fooChild2 = new Foo();
        fooChild2.setId(3);
        fooChild2.setFooList(new ArrayList<>());
    
        foo.setFooList(Arrays.asList(fooChild, fooChild2));
    
        Bar bar = new Bar();
        bar.setFooList(FooJsonSimplifiedSerializationWrapper.convertFromFoo(Arrays.asList(foo)));
    
        System.out.println(new ObjectMapper().writeValueAsString(foo));
        System.out.println(new ObjectMapper().writeValueAsString(bar));
    }
    

    此代码将打印:

    Foo serialization: {"id":1,"fooList":[{"id":2,"fooList":[]},{"id":3,"fooList":[]}]}

    Bar serialization: {"fooList":[{"id":1,"fooList":[2,3]}]}

    另一个解决方案可能涉及使用 Views 具有 @JsonView 注释和定制视图以适应您的需要,但在我看来是一个更麻烦的解决方案。