首页 > 解决方案 > 使用 Jackson 序列化和反序列化树结构

问题描述

我有一个树结构,其中包含以下对象,我需要使用 Jackson 对其进行序列化和反序列化,但不知道该怎么做。

Type

Type有名字和版本。它也可能有父类型和子类型。

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name")
final class Type {

    private final PrefixedName name;
    private final Integer version;
    private final Set<Type> subTypes = new HashSet<>();
    private final Type parent;
    private final PrefixedName parentName;


    Type(final PrefixedName name, final Integer version) {
        this(name, version, null);
    }

    @JsonCreator
    Type(@JsonProperty("name") @JsonDeserialize(keyUsing = PrefixedNameKeyDeserializer.class) final PrefixedName name,
            @JsonProperty("typeVersion") final Integer version, @JsonProperty("parent") final Type parent) {
        this.name = Objects.requireNonNull(name);

        Preconditions.checkArgument(version > 0, "Version number must be positive");
        this.version = version;

        this.parent = parent;
        if (parent != null) {
            this.parentName = parent.getName();
            parent.addSubType(this);
        } else {
            this.parentName = null;
        }
    }

    // Other methods to add sub-types; and getters for all properties omitted

}

Model

Model包含树的根——一个Type和一个版本。

final class Model {

    private final Integer version;
    private final Type root;

    @JsonCreator
    Model(@JsonProperty("modelVersion") final Integer version, @JsonProperty("root") final Type root) {
        this.version = version;
        this.root = root;
    }

使用杰克逊的ObjectMapper序列化看起来如我所料:

{
   "root":{
      "parent":null,
      "name":{
         "localName":"Base",
         "prefix":"schema"
      },
      "subTypes":[
         {
            "parent":{
               "localName":"Base",
               "prefix":"schema"
            },
            "name":{
               "localName":"Person",
               "prefix":"schema"
            },
            "subTypes":[
               {
                  "parent":{
                     "localName":"Person",
                     "prefix":"schema"
                  },
                  "name":{
                     "localName":"employee",
                     "prefix":"schema"
                  },
                  "subTypes":[

                  ],
                  "version":1
               }
            ],
            "version":1
         },
         {
            "parent":{
               "localName":"Base",
               "prefix":"schema"
            },
            "name":{
               "localName":"organisation",
               "prefix":"schema"
            },
            "subTypes":[

            ],
            "version":1
         },
         {
            "parent":{
               "localName":"Base",
               "prefix":"schema"
            },
            "name":{
               "localName":"CreativeWork",
               "prefix":"schema"
            },
            "subTypes":[
               {
                  "parent":{
                     "localName":"CreativeWork",
                     "prefix":"schema"
                  },
                  "name":{
                     "localName":"Journal",
                     "prefix":"schema"
                  },
                  "subTypes":[

                  ],
                  "version":1
               },
               {
                  "parent":{
                     "localName":"CreativeWork",
                     "prefix":"schema"
                  },
                  "name":{
                     "localName":"Book",
                     "prefix":"schema"
                  },
                  "subTypes":[

                  ],
                  "version":1
               }
            ],
            "version":1
         }
      ],
      "version":1
   },
   "version":8
}

Type请注意,类上的注释@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name")意味着该parent属性仅使用该属性编写name- 这是为了防止无限递归和StackOverflowException- 如果有更好的方法来做到这一点,我很乐意改变。

但是,反序列化失败,将属性NullPointerException设置为:nameType

this.name = Objects.requireNonNull(name);

我已经通过代码进行了调试,并且看到 Jackson 正在PrefixedName将父级的(如下所示的类)的两个属性捕获为“未知”属性——我不确定这是否与问题有关,但它可能有用。

PrefixedName

这是两个带有 Jackson 注释的 String 属性的简单AutoValue类:

@AutoValue
@SuppressWarnings("squid:S1610")
@JsonDeserialize(builder = AutoValue_PrefixedName.Builder.class)
abstract class PrefixedName {

    static Builder builder() {
        return new AutoValue_PrefixedName.Builder();
    }

    @JsonProperty
    abstract String prefix();

    @JsonProperty
    abstract String localName();

    @AutoValue.Builder
    abstract static class Builder {

        @JsonProperty
        abstract Builder prefix(final String prefix);

        @JsonProperty
        abstract Builder localName(final String localName);

        abstract PrefixedName build();
    }
}

谢谢你尽你所能的帮助。

标签: javaserializationdata-structurestreejackson

解决方案


推荐阅读