У меня есть древовидная структура со следующими объектами, которые мне нужны для сериализации и десериализации с использованием Джексона, но я не могу понять, как это сделать.
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
содержит root дерева - 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
в строке, устанавливающей свойство name
в Type
:
this.name = Objects.requireNonNull(name);
Я отлаживал код и видел, что Джексон захватывает два свойства PrefixedName
(класс показано ниже) для родителя как «неизвестные» свойства - я не уверен, связано ли это с проблемой, но это может быть полезно.
PrefixedName
Это просто AutoValue класс двух свойств String с аннотациями Джексона:
@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();
}
}
Спасибо за любую помощь, которую вы можете предложить.