根据id反序列化父对象
Deserializing Parent Object based on id
我正在尝试反序列化包含在 "module" 对象中的 "onclick" 事件,如下所示 JSON:
{
"parent": {
"id": 0,
"children": [{
"child": {
"id": 1,
"description": "A",
"parent": 0,
"events": [{
"onclick": {
"source": 1
}
}]
}
}]
}
}
class结构非常简单:
View (Interface)
+- AbstractView
+- Parent
+- Child
Event (Interface)
+- AbstractEvent
+- OnClick
抽象事件:
public abstract class AbstractEvent implements Event {
private View source;
protected AbstractEvent() {}
protected AbstractEvent(View source) {
this.source = source;
}
@Override
public View getSource() {
return source;
}
@Override
public void setSource(View source) {
this.source = source;
}
}
我正在使用 Mixins,因为该模型在几个不同的项目之间使用。
ViewMixIn:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "type")
@JsonSubTypes({
@Type(value = Parent.class, name = "parent"),
@Type(value = Child.class, name = "child")
})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public abstract class ViewMixIn {
}
事件混合输入:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "class")
@JsonSubTypes({
@Type(value = OnClick.class, name = "onclick")
})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "source")
public abstract class EventMixIn {
}
简化模块:
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.setMixInAnnotations(AbstractView.class, ViewMixIn.class);
context.setMixInAnnotations(AbstractEvent.class, EventMixIn.class);
}
ObjectMapper 配置:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimplifiedModule())
.setSerializationInclusion(NON_NULL)
.setSerializationInclusion(NON_EMPTY)
.enableDefaultTyping()
.enableDefaultTyping(NON_FINAL, As.WRAPPER_OBJECT)
.setVisibilityChecker(
mapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
如图所示,模型已正确序列化,但在反序列化过程中出现以下错误:
WARN 11:46:04:949 br.com.pdcore.appmaker.middleware.simplified.SimplifiedModelTest - Could not deserialise Parent.
com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (VALUE_NUMBER_INT), expected START_OBJECT: need JSON Object to contain As.WRAPPER_OBJECT type information for class br.com.pdcore.appmaker.middleware.simplified.model.view.View
at [Source: {"parent":{"id":0,"children":{"java.util.ArrayList":[{"child":{"id":1,"description":"A","parent":0,"events":{"java.util.ArrayList":[{"onclick":{"source":1}}]}}},{"child":{"id":2,"description":"B","parent":0,"events":{"java.util.ArrayList":[{"onclick":{"source":2}}]}}},{"child":{"id":3,"description":"C","parent":0,"events":{"java.util.ArrayList":[{"onclick":{"source":3}}]}}},{"child":{"id":4,"description":"D","parent":0,"events":{"java.util.ArrayList":[{"onclick":{"source":4}}]}}},{"child":{"id":5,"description":"E","parent":0,"events":{"java.util.ArrayList":[{"onclick":{"source":5}}]}}}]}}}; line: 1, column: 145] (through reference chain: br.com.pdcore.appmaker.middleware.simplified.model.view.Parent["children"]->java.util.ArrayList[0]->br.com.pdcore.appmaker.middleware.simplified.model.view.Child["events"]->java.util.ArrayList[0]->br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick["source"])
好像不理解 "source" id 指的是包装 onclick 节点的子对象。
如果我更改 MixIn 定义:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "name")
至:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type")
我仍然遇到类似的错误:
WARN 12:04:35:126 br.com.pdcore.appmaker.middleware.simplified.SimplifiedModelTest - Could not deserialise Parent.
com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (VALUE_NUMBER_INT), expected FIELD_NAME: missing property '@class' that is to contain type id (for class br.com.pdcore.appmaker.middleware.simplified.model.view.View)
at [Source: {"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Parent","id":0,"children":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Child","id":1,"description":"A","parent":0,"events":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick","source":1}]]},{"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Child","id":2,"description":"B","parent":0,"events":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick","source":2}]]},{"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Child","id":3,"description":"C","parent":0,"events":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick","source":3}]]},{"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Child","id":4,"description":"D","parent":0,"events":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick","source":4}]]},{"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Child","id":5,"description":"E","parent":0,"events":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick","source":5}]]}]]}; line: 1, column: 331] (through reference chain: br.com.pdcore.appmaker.middleware.simplified.model.view.Parent["children"]->java.util.ArrayList[0]->br.com.pdcore.appmaker.middleware.simplified.model.view.Child["events"]->java.util.ArrayList[0]->br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick["source"])
仔细阅读 JsonIdentityInfo 的 javadoc 后,发现了以下问题:
Object id has to be serialized as a property in case of POJOs; object identity is currently NOT support for JSON Array types (Java arrays or Lists) or Java Map types.
所以基本上我需要生成一个自定义反序列化器。
我正在尝试反序列化包含在 "module" 对象中的 "onclick" 事件,如下所示 JSON:
{
"parent": {
"id": 0,
"children": [{
"child": {
"id": 1,
"description": "A",
"parent": 0,
"events": [{
"onclick": {
"source": 1
}
}]
}
}]
}
}
class结构非常简单:
View (Interface)
+- AbstractView
+- Parent
+- Child
Event (Interface)
+- AbstractEvent
+- OnClick
抽象事件:
public abstract class AbstractEvent implements Event {
private View source;
protected AbstractEvent() {}
protected AbstractEvent(View source) {
this.source = source;
}
@Override
public View getSource() {
return source;
}
@Override
public void setSource(View source) {
this.source = source;
}
}
我正在使用 Mixins,因为该模型在几个不同的项目之间使用。
ViewMixIn:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "type")
@JsonSubTypes({
@Type(value = Parent.class, name = "parent"),
@Type(value = Child.class, name = "child")
})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public abstract class ViewMixIn {
}
事件混合输入:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "class")
@JsonSubTypes({
@Type(value = OnClick.class, name = "onclick")
})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "source")
public abstract class EventMixIn {
}
简化模块:
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.setMixInAnnotations(AbstractView.class, ViewMixIn.class);
context.setMixInAnnotations(AbstractEvent.class, EventMixIn.class);
}
ObjectMapper 配置:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimplifiedModule())
.setSerializationInclusion(NON_NULL)
.setSerializationInclusion(NON_EMPTY)
.enableDefaultTyping()
.enableDefaultTyping(NON_FINAL, As.WRAPPER_OBJECT)
.setVisibilityChecker(
mapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
如图所示,模型已正确序列化,但在反序列化过程中出现以下错误:
WARN 11:46:04:949 br.com.pdcore.appmaker.middleware.simplified.SimplifiedModelTest - Could not deserialise Parent. com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (VALUE_NUMBER_INT), expected START_OBJECT: need JSON Object to contain As.WRAPPER_OBJECT type information for class br.com.pdcore.appmaker.middleware.simplified.model.view.View at [Source: {"parent":{"id":0,"children":{"java.util.ArrayList":[{"child":{"id":1,"description":"A","parent":0,"events":{"java.util.ArrayList":[{"onclick":{"source":1}}]}}},{"child":{"id":2,"description":"B","parent":0,"events":{"java.util.ArrayList":[{"onclick":{"source":2}}]}}},{"child":{"id":3,"description":"C","parent":0,"events":{"java.util.ArrayList":[{"onclick":{"source":3}}]}}},{"child":{"id":4,"description":"D","parent":0,"events":{"java.util.ArrayList":[{"onclick":{"source":4}}]}}},{"child":{"id":5,"description":"E","parent":0,"events":{"java.util.ArrayList":[{"onclick":{"source":5}}]}}}]}}}; line: 1, column: 145] (through reference chain: br.com.pdcore.appmaker.middleware.simplified.model.view.Parent["children"]->java.util.ArrayList[0]->br.com.pdcore.appmaker.middleware.simplified.model.view.Child["events"]->java.util.ArrayList[0]->br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick["source"])
好像不理解 "source" id 指的是包装 onclick 节点的子对象。
如果我更改 MixIn 定义:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "name")
至:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type")
我仍然遇到类似的错误:
WARN 12:04:35:126 br.com.pdcore.appmaker.middleware.simplified.SimplifiedModelTest - Could not deserialise Parent. com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (VALUE_NUMBER_INT), expected FIELD_NAME: missing property '@class' that is to contain type id (for class br.com.pdcore.appmaker.middleware.simplified.model.view.View) at [Source: {"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Parent","id":0,"children":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Child","id":1,"description":"A","parent":0,"events":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick","source":1}]]},{"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Child","id":2,"description":"B","parent":0,"events":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick","source":2}]]},{"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Child","id":3,"description":"C","parent":0,"events":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick","source":3}]]},{"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Child","id":4,"description":"D","parent":0,"events":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick","source":4}]]},{"type":"br.com.pdcore.appmaker.middleware.simplified.model.view.Child","id":5,"description":"E","parent":0,"events":["java.util.ArrayList",[{"type":"br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick","source":5}]]}]]}; line: 1, column: 331] (through reference chain: br.com.pdcore.appmaker.middleware.simplified.model.view.Parent["children"]->java.util.ArrayList[0]->br.com.pdcore.appmaker.middleware.simplified.model.view.Child["events"]->java.util.ArrayList[0]->br.com.pdcore.appmaker.middleware.simplified.model.event.OnClick["source"])
仔细阅读 JsonIdentityInfo 的 javadoc 后,发现了以下问题:
Object id has to be serialized as a property in case of POJOs; object identity is currently NOT support for JSON Array types (Java arrays or Lists) or Java Map types.
所以基本上我需要生成一个自定义反序列化器。