简体   繁体   English

强制属性在 Jackson 中序列化为身份

[英]Force a property to serialize into identity in Jackson

I have a class with我有一堂课

(disclaimer, I am writing in Kotlin, but I translate it into Java so more people can read it) (免责声明,我是用 Kotlin 编写的,但我将其翻译成 Java,以便更多人可以阅读它)

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

I want to serialize another object which contains a list of Foo s, but I want all entries in the serialized fooList to be IDs, not objects.我想序列化另一个包含Foo列表的对象,但我希望序列化的fooList中的所有条目都是 ID,而不是对象。 One solution that came to mind was to sort them topologically in reverse order before serialization, as they form a directed acyclic graph.想到的一个解决方案是在序列化之前以相反的拓扑顺序对它们进行排序,因为它们形成了有向无环图。 But that's obviously not a perfect solution, so I'm wondering if there's an annotation or an otherwise clean Jackson way to do something like that.但这显然不是一个完美的解决方案,所以我想知道是否有注释或其他干净的杰克逊方式来做这样的事情。

EDIT:编辑:
The class that contains a list of Foo looks like this:包含 Foo 列表的类如下所示:

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

And when I deserialize a Bar instance from this JSON:当我从这个 JSON 反序列化一个Bar实例时:

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

And then I serialize it back, I want the output to be the same as the input, but instead it's this:然后我将它序列化回来,我希望输出与输入相同,但它是这样的:

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

You could create a class that extends from Foo class to offer an alternative serialization for fooList using the annotation @JsonGetter , like a wrapper.您可以创建一个从Foo类扩展的类,以使用注释@JsonGetterfooList提供替代序列化,就像包装器一样。

Foo class: Foo类:

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 class: 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 is the Foo wrapper for serialization and it has a method to convert from Lst<Foo> to List< FooFooJsonSimplifiedSerializationWrapper > that you will have to call at some point before serializing: FooFooJsonSimplifiedSerializationWrapper是用于序列化的Foo包装器,它具有将FooFooJsonSimplifiedSerializationWrapper Lst<Foo>转换为 List< FooFooJsonSimplifiedSerializationWrapper > 的方法,您必须在序列化之前调用它:

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 with some tests: 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));
}

This code will print:此代码将打印:

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

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

Another solution could involve using Views with @JsonView annotation and customizing the views to adapt the serialization to your needs but in my opinion is a more cumbersome solution.另一种解决办法涉及使用Views@JsonView注释和自定义视图的系列化适应您的需求,但在我看来是一个比较麻烦的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM