【问题标题】:@JsonIdentityInfo serialization of items@JsonIdentityInfo 项目的序列化
【发布时间】:2021-11-07 14:05:02
【问题描述】:

我正在尝试使用@JsonItentityInfo 序列化关系以避免循环引用。我创建了一个测试来尝试测试序列化的结果,我发现杰克逊的行为不像我预期的那样。序列化不是我想象的那样,事实上,当我尝试反序列化序列化对象时,会引发异常。我使用的代码是:

public class Test {
    
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
    public static class A {
        private final String id;
        private final String name;
        private final B b;
        
        public A(final String id, final String name, final B b) {
            this.id = id;
            this.name = name;
            this.b = b;
        }
        
        public String getId() {
            return this.id;
        }

        public String getName() {
            return this.name;
        }

        public B getB() {
            return this.b;
        }

    }
    
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
    public static class B {

        private final String id;
        private final String name;
        
        public B(final String id, final String name) {
            this.id = id;
            this.name = name;
        }
        
        public String getId() {
            return this.id;
        }

        public String getName() {
            return this.name;
        }

    }

    public static void main(final String[] args) {
        try {
            System.out.println(
                    new ObjectMapper().writeValueAsString(new A("1", "a", new B("2", "b"))));
        } catch (final JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

据我了解,输出应该是

{"id":"1","name":"a","b":"2"}

但测试返回

{"id":"1","name":"a","b":{"id":"2","name":"b"}}

事实上,当试图读取序列化字符串时,jackson 会抛出异常。我做错了什么?

谢谢大家的帮助

编辑:示例不完整。对象应该被另一个对象包裹起来,所以这两个是序列化的。

package lvillap.deliverytoolsserver.domain;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Test {

    private final A a;
    private final B b;

    public Test(final A a, final B b) {
        this.a = a;
        this.b = b;
    }

    public A getA() {
        return this.a;
    }

    public B getB() {
        return this.b;
    }

    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
    public static class A {

        private final String id;
        private final String name;
        @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
        @JsonIdentityReference(alwaysAsId = true)
        private final B b;

        public A(final String id, final String name, final B b) {
            this.id = id;
            this.name = name;
            this.b = b;
        }

        public String getId() {
            return this.id;
        }

        public String getName() {
            return this.name;
        }

        public B getB() {
            return this.b;
        }

    }

    public static class B {

        private final String id;
        private final String name;

        public B(final String id, final String name) {
            this.id = id;
            this.name = name;
        }

        public String getId() {
            return this.id;
        }

        public String getName() {
            return this.name;
        }

    }

    public static void main(final String[] args) {
        try {
            final B b = new B("2", "b");
            final A a = new A("1", "a", b);
            System.out.println(new ObjectMapper().writeValueAsString(new Test(a, b)));
        } catch (final JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

以这种方式实现时,结果是预期的: {"a":{"id":"1","name":"a","b":"2"},"b":{"id":"2","name":"b "}}

谢谢大家的帮助!

【问题讨论】:

    标签: java serialization jackson jackson-databind


    【解决方案1】:

    在默认情况下,你得到的正是你应该得到的。

    你可以做的是改变你class A,如下所示。

    请注意,我已更改 getB() 方法。它不再返回class B 的实例。它返回该class B 实例的id 属性。

    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
    public static class A {
        private final String id;
        private final String name;
        private final B b;
    
        public A(final String id, final String name, final B b) {
            this.id = id;
            this.name = name;
            this.b = b;
        }
    
        public String getId() {
            return this.id;
        }
    
        public String getName() {
            return this.name;
        }
    
        public String getB() {
            return this.b.id;
        }
    
    }
    

    您也可以为class B 创建自定义序列化程序。

    【讨论】:

    • 你说得对,我会编辑这个问题,因为它不完整。 A 和 B 应该在另一个对象内。
    【解决方案2】:

    如果你愿意

    {"id":"1","name":"a","b":"2"}
    

    那你把private final B b;改成private final String b;,去掉B类,改代码

    new ObjectMapper().writeValueAsString(new A("1", "a", "2"));
    

    您也可以删除@JsonIdentityInfo

    我认为一切都很简单,Object Java 将转换为 Object json,因此当您在 class A 中包含 class B 作为字段时,您就有了嵌套的 json 对象。

    【讨论】:

    • 你说得对,我会编辑这个问题,因为它不完整。 A 和 B 应该在另一个对象内。
    猜你喜欢
    • 2019-03-27
    • 1970-01-01
    • 2018-04-05
    • 2015-07-11
    • 1970-01-01
    • 2014-08-04
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    相关资源
    最近更新 更多