ジャクソンと遊んだ後、私は次のような解決策に出た。私のためにうまく動作します。
まず、我々は唯一のjava.lang.Object
のためのシリアライズ/ deserilizationを入力処理するカスタムTypeResolverを作成する多型
@JsonTypeResolver(MyTypeResolver.class)
@JsonTypeIdResolver(MyTypeIdResolver.class)
@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface ObjectMixin {
}
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
mapper.addMixIn(Object.class, ObjectMixin.class);
すべてを作ります。
public class MyTypeResolver extends StdTypeResolverBuilder {
@Override
public TypeSerializer buildTypeSerializer(SerializationConfig config, JavaType baseType, Collection<NamedType> subtypes) {
return useForType(baseType) ? super.buildTypeSerializer(config, baseType, subtypes) : null;
}
@Override
public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, JavaType baseType, Collection<NamedType> subtypes) {
return useForType(baseType) ? super.buildTypeDeserializer(config, baseType, subtypes) : null;
}
public boolean useForType(JavaType t) {
return t.isJavaLangObject();
}
}
タイプIdResolverはIDマジックを処理します。この例では、すべてがハードコードされていますが、実際のコードでは、それははるかに良いと思っています。 :)
public class MyTypeIdResolver extends TypeIdResolverBase {
@Override
public String idFromValue(Object value) {
return getId(value);
}
@Override
public String idFromValueAndType(Object value, Class<?> suggestedType) {
return getId(value);
}
@Override
public JsonTypeInfo.Id getMechanism() {
return JsonTypeInfo.Id.CUSTOM;
}
private String getId(Object value) {
if (value instanceof ListWrapper.MyMapListWrapper) {
return "MyMap[]";
}
if (value instanceof ListWrapper.Child1ListWrapper) {
return "Child1[]";
}
if (value instanceof ListWrapper && !((ListWrapper) value).getValues().isEmpty()) {
return ((ListWrapper) value).getValues().get(0).getClass().getSimpleName() + "[]";
}
return value.getClass().getSimpleName();
}
@Override
public JavaType typeFromId(DatabindContext context, String id) throws IOException {
if (id.endsWith("[]")) {
if (id.startsWith("Child1")) {
return TypeFactory.defaultInstance().constructParametricType(ListWrapper.class, Child1.class);
}
if (id.startsWith("MyMap")) {
return TypeFactory.defaultInstance().constructSpecializedType(TypeFactory.unknownType(), ListWrapper.MyMapListWrapper.class);
}
}
if (id.equals("Child1")) {
return TypeFactory.defaultInstance().constructSpecializedType(TypeFactory.unknownType(), Child1.class);
}
if (id.equals("MyMap")) {
return TypeFactory.defaultInstance().constructSpecializedType(TypeFactory.unknownType(), MyMap.class);
}
return TypeFactory.unknownType();
}
}
は、私がListWrapper
クラスとサブクラスを持っている{"@type: "...", "@values": ...}
リストを処理することができます。 Todo:カスタム非直列化ロジックを使用してこれを再実装します。
public class ListWrapper<T> {
@JsonProperty("@values")
private List<T> values;
public static class MyMapListWrapper extends ListWrapper<MyMap> {
}
public static class Child1ListWrapper extends ListWrapper<Child1> {
}
}
これは、サブクラスの作成をスキップすることが可能ですが、その後の型情報は、一つ一つの要素に追加されます。 java.lang.*
もちろん、クラスには型情報はありません。
モデルは以下のとおりです。
public class Parent {
private String prop;
private Child1 child1;
private MyMap map;
}
public class Child1 {
private int anInt;
}
テストコード:
@Test
public void shouldDoTheTrick() throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
mapper.addMixIn(Object.class, ObjectMixin.class);
Parent parent = new Parent("Hello", new Child1(-1), new MyMap() {{
put("JustString", "JustValue");
put("List_With_All_MyMaps", new ListWrapper.MyMapListWrapper(new ArrayList<MyMap>() {{
add(new MyMap() {{
put("Key", "Value");
put("object", new Child1(2));
}});
add(new MyMap() {{
put("Key", "Value");
}});
}}));
put("List_With_All_Child1", new ListWrapper.Child1ListWrapper(new ArrayList<Child1>() {{
add(new Child1(41));
add(new Child1(42));
}}));
}});
String valueAsString = mapper.writeValueAsString(parent);
Parent deser = mapper.readValue(valueAsString, Parent.class);
assertEquals(parent, deser);
}
JSON出力:
{
"prop" : "Hello",
"child1" : {
"anInt" : -1
},
"map" : {
"JustString" : "JustValue",
"List_With_All_MyMaps" : {
"@type" : "MyMap[]",
"@values" : [ {
"Key" : "Value",
"object" : {
"@type" : "Child1",
"anInt" : 2
}
}, {
"Key" : "Value"
} ]
},
"List_With_All_Child1" : {
"@type" : "Child1[]",
"@values" : [ {
"anInt" : 41
}, {
"anInt" : 42
} ]
}
}
}
UPD:実際の実装例https://github.com/sdl/dxa-web-application-java/commit/7a36a9598ac2273007806285ea4d854db1434ac5
投稿しないでくださいのコードへのリンクあなたの質問はスタックオーバーフローでここにあります。 – CraigR8806
'ObjectMapper'を試してみてください –