我有一个基类和两个子库:
public /*abstract*/ class TargetPoi {
private String poiId;
...
}
public class TargetSub1Poi extends TargetPoi {
private String oneMoreId;
...
}
public class TargetSub2Poi extends TargetPoi {
...
}
是否可以声明基类抽象? ...如果我使用 abstract 关键字,当我发送带有请求的JSON时,我总是会遇到异常......
Exception Description: This class does not define a public default constructor, or the constructor raised an exception.
Internal Exception: java.lang.InstantiationException
Descriptor: XMLDescriptor(com.foo.bar.TargetPoi --> [])
当请求体中带有JSON的POST请求进入Jersy资源时,我想将JSON反序列化为正确的TargetPoi子类。 JSON:
{
"requestId": "84137f1ab38f4bf585d13984fc07c621",
"startTime": "2013-10-30T18:30:00+02:00",
"endTime": "2013-10-30T18:45:00+02:00",
"targetPoi":
{
"poiId": "0000000602",
"oneMoreId": "1"
},
"type": "Block",
"notification": true
}
我的资源有一种以这种方式定义的方法......
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response doReservation(final ReservationDO reservationDO
, @QueryParam("serviceType") final String serviceType) {
...
}
JSON应在此类中反序列化:
@XmlRootElement
public class ReservationDO<T extends TargetPoi>
{
public String requestId;
public String startTime;
public String endTime;
public String serviceType;
public T targetPoi;
...
}
如何告诉Jackson将targetPoi的JSON正确绑定到正确的子类型(TargetSub1Poi)? serviceType 可以告诉我targetPoi要绑定到哪个子类型......但我认为这些信息不能用于Jackson,是吗?当我在edoreservation方法中打印出反序列化的JSON时,带有原始JSON的 oneMoreId 部分将丢失。
我是否必须提供任何TypeInfo,或者我可以在没有它的情况下实现它吗?
答案 0 :(得分:0)
可以声明父类抽象并具有通用字段。您只需要告诉Jackson使用哪个子类型来创建对象的实例。可以使用the Jackson polymorphic deserialization wiki page中所述的@JsonTypeInfo
注释来完成此操作。
以下是一个例子:
public class JacksonPoi {
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "type")
public static abstract class TargetPoi {
public String poiId;
}
@JsonTypeName("sub1")
public static class TargetSub1Poi extends TargetPoi {
public String oneMoreId;
@Override
public String toString() {
return "TargetSub1Poi{" +
"poiId='" + poiId + '\'' +
"oneMoreId='" + oneMoreId + '\'' +
'}';
}
}
@JsonTypeName("sub2")
public static class TargetSub2Poi extends TargetPoi {
public String twoMoreId;
@Override
public String toString() {
return "TargetSub2Poi{" +
"poiId='" + poiId + '\'' +
"twoMoreId='" + twoMoreId + '\'' +
'}';
}
}
public static class Bean<T extends TargetPoi> {
public String field;
public T poi;
@Override
public String toString() {
return "Bean{" +
"field='" + field + '\'' +
", poi=" + poi +
'}';
}
}
public static final String JSON = "{\n" +
"\"poi\": \n" +
"{\n" +
" \"type\": \"sub1\",\n" +
" \"poiId\": \"0000000602\",\n" +
" \"oneMoreId\": \"1\"\n" +
"},\n" +
"\"field\": \"value1\"\n" +
"}";
public static final String JSON2 = "{\n" +
"\"poi\": \n" +
"{\n" +
" \"type\": \"sub2\",\n" +
" \"poiId\": \"0000000602\",\n" +
" \"twoMoreId\": \"13\"\n" +
"},\n" +
"\"field\": \"value2\"\n" +
"}";
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.registerSubtypes(TargetSub1Poi.class, TargetSub2Poi.class);
Bean<TargetSub1Poi> poi1 = mapper.readValue(JSON, new TypeReference<Bean<TargetSub1Poi>>() {});
System.out.println(poi1);
Bean<TargetSub2Poi> poi2 = mapper.readValue(JSON2, new TypeReference<Bean<TargetSub2Poi>>() {});
System.out.println(poi2);
}
}
输出:
Bean{field='value1', poi=TargetSub1Poi{poiId='0000000602'oneMoreId='1'}}
Bean{field='value2', poi=TargetSub2Poi{poiId='0000000602'twoMoreId='13'}}