【问题标题】:Force a property to serialize into identity in Jackson强制属性在杰克逊中序列化为身份
【发布时间】:2018-09-18 15:43:19
【问题描述】:

我有一堂课

(免责声明,我用 Kotlin 编写,但我将其翻译成 Java,以便更多人阅读)

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

我想序列化另一个包含Foos 列表的对象,但我希望序列化fooList 中的所有条目都是ID,而不是对象。想到的一种解决方案是在序列化之前以相反的顺序对它们进行拓扑排序,因为它们形成有向无环图。但这显然不是一个完美的解决方案,所以我想知道是否有注释或其他干净的杰克逊方式来做类似的事情。

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

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

当我从这个 JSON 反序列化 Bar 实例时:

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

然后我将它序列化回来,我希望输出与输入相同,但它是这样的:

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

【问题讨论】:

  • 你的问题不是很清楚。您能否添加包含 Foo 对象列表的另一个类的代码(如果它存在)。您能否在给定一些输入数据的情况下添加您期望的 json 输出数据。
  • 我认为这很清楚,对不起。就可以了。

标签: java jackson jsonidentityinfo


【解决方案1】:

您可以创建一个扩展自 Foo 类的类,以使用注解 @JsonGetterfooList 提供替代序列化,例如包装器。

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类:

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 是用于序列化的Foo 包装器,它有一个方法可以将Lst&lt;Foo&gt; 转换为ListFooFooJsonSimplifiedSerializationWrapper>,您必须在序列化之前的某个时间点调用它:

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 注释并自定义视图以使序列化适应您的需求,但在我看来这是一个更麻烦的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-24
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 1970-01-01
    • 2020-04-16
    相关资源
    最近更新 更多