Java 如何将JSON反序列化到接口?
我无法将JSON反序列化到以下示例中实现Basic接口的一些类ChildA、ChildB等Java 如何将JSON反序列化到接口?,java,json,jackson,polymorphism,deserialization,Java,Json,Jackson,Polymorphism,Deserialization,我无法将JSON反序列化到以下示例中实现Basic接口的一些类ChildA、ChildB等 @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = InstagramUser.class, name = "Ch
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = InstagramUser.class, name = "ChildA")
})
public interface Basic {
getName();
getCount();
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeName("ChildA")
public class ChildA implements Basic { ... }
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeName("ChildB")
public class ChildB implements Basic { ... }
...
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Response<E extends Basic> {
@JsonProperty("data")
private List<E> data;
public List<E> getData() {
return data;
}
public void setData(List<E> data) {
this.data = data;
}
}
// deserialization
HTTPClient.objectMapper.readValue(
response,
(Class<Response<ChildA>>)(Class<?>) Response.class
)
没有在所有类型对象中显示的属性,因此它们完全不同。但正如您在readValue行中看到的,我知道预期的类型。如何构造JsonTypeInfo和JsonSubTypes注释以按预期类反序列化JSON?
我找到的不是确切的解决方案,而是一种变通方法。我使用自定义响应类ChildAResponse并将其传递给ObjectMapper.readValue()
方法
类ChildAResponse扩展响应{}
//反序列化
HTTPClient.objectMapper.readValue(
答复,,
儿童体育课
)
因此,不再需要接口上的JsonTypeInfo和JsonSubTypes注释。根据这里的阅读,我有点像你一样的问题:我创建了我自己的解决方案,它基本上包括创建我自己的反序列化程序,诀窍是使用/标识JSON中的特定属性,以了解反序列化应返回的实例类型,例如:
public interface Basic {
}
第一个孩子:
public class ChildA implements Basic {
private String propertyUniqueForThisClass;
//constructor, getters and setters ommited
}
第二个孩子:
public class ChildB implements Basic {
private String childBUniqueProperty;
//constructor, getters and setters ommited
}
反序列化程序(BasicDeserializer.java)类似于:
public class BasicDeserializer extends StdDeserializer<Basic> {
public BasicDeserializer() {
this(null);
}
public BasicDeserializer(final Class<?> vc) {
super(vc);
}
@Override
public Basic deserialize(final JsonParser jsonParser,
final DeserializationContext deserializationContext)
throws IOException {
final JsonNode node = jsonParser.getCodec().readTree(jsonParser);
final ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec();
// look for propertyUniqueForThisClass property to ensure the message is of type ChildA
if (node.has("propertyUniqueForThisClass")) {
return mapper.treeToValue(node, ChildA.class);
// look for childBUniqueProperty property to ensure the message is of type ChildB
} else if (node.has("childBUniqueProperty")) {
return mapper.treeToValue(node, ChildB.class);
} else {
throw new UnsupportedOperationException(
"Not supported class type for Message implementation");
}
}
}
对于测试:
@Test
public void testJsonToChildA() throws IOException {
String message = "{\"propertyUniqueForThisClass\": \"ChildAValue\"}";
Basic basic = BasicUtils.buildMessageFromJSON(message);
assertNotNull(basic);
assertTrue(basic instanceof ChildA);
System.out.println(basic);
}
@Test
public void testJsonToChildB() throws IOException {
String message = "{\"childBUniqueProperty\": \"ChildBValue\"}";
Basic basic = BasicUtils.buildMessageFromJSON(message);
assertNotNull(basic);
assertTrue(basic instanceof ChildB);
System.out.println(basic);
}
源代码可以在以下位置找到:是您要在json中反序列化的类型吗?数据中的对象是预期格式(ChildA),但没有包含类型信息的属性。列表中的所有对象都相同。不幸的是,我无法更改JSON。这就是问题所在——您的注释告诉jackson在JSON中需要一个类型,但没有
private static final ObjectMapper MAPPER;
// following good software practices, utils can not have constructors
private BasicUtils() {}
static {
final SimpleModule module = new SimpleModule();
MAPPER = new ObjectMapper();
module.addDeserializer(Basic.class, new BasicDeserializer());
MAPPER.registerModule(module);
}
public static String buildJSONFromMessage(final Basic message)
throws JsonProcessingException {
return MAPPER.writeValueAsString(message);
}
public static Basic buildMessageFromJSON(final String jsonMessage)
throws IOException {
return MAPPER.readValue(jsonMessage, Basic.class);
}
@Test
public void testJsonToChildA() throws IOException {
String message = "{\"propertyUniqueForThisClass\": \"ChildAValue\"}";
Basic basic = BasicUtils.buildMessageFromJSON(message);
assertNotNull(basic);
assertTrue(basic instanceof ChildA);
System.out.println(basic);
}
@Test
public void testJsonToChildB() throws IOException {
String message = "{\"childBUniqueProperty\": \"ChildBValue\"}";
Basic basic = BasicUtils.buildMessageFromJSON(message);
assertNotNull(basic);
assertTrue(basic instanceof ChildB);
System.out.println(basic);
}