@JsonIdentityInfo 项目的序列化

@JsonIdentityInfo serialization of items

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

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"}

但是考试returns

{"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 "}}

谢谢大家的帮助!

如果你愿意

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

然后你把private final B b;改成private final String b;,去掉classB,改代码

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

您还可以删除 @JsonIdentityInfo

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

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

你能做的就是改变你 class A 如下。

请注意,我已更改 getB() 方法。它不再是 class B 的 return 个实例。它 return 那个 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 创建自定义序列化程序。