今天早上我花了一些时间来解决这个问题.一个有趣的用例.我想出了怎么做,但我不得不稍微改变你的json.这不是绝对必要的,但是类型转换不是您的问题的一部分,因此我们可以根据需要进行跟进:)
你的json:
artur@pandaadb:~/tmp/test$cat 1.json
{
"eventType": "1",
"params": {
"field1" : 10
}
}
artur@pandaadb:~/tmp/test$cat 2.json
{
"eventType": "2",
"params": {
"field2" : "10"
}
}
我正在使用这两个文件来执行请求.请注意,我将eventType更改为String而不是数字.我稍后会指出这一点.
你的模型对象:
public class Stats {
@JsonProperty
int eventType;
public Params params;
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.EXTERNAL_PROPERTY, property="eventType")
@JsonSubTypes({ @Type(value = Param1.class, name = "1"), @Type(value = Param2.class, name = "2") })
public void setParams(Params params) {
this.params = params;
}
}
我正在使用JsonTypeInfo,这是这样做的:
JsonTypeInfo.Id.NAME
逻辑类型名称,在您的情况下,它是属性“eventType”
JsonTypeInfo.As.EXTERNAL_PROPERTY
表示外部属性用于反序列化上下文.您只能在属性上使用它,而不能在Params本身上使用类注释.这就是为什么我注释setter方法而不是接口类.
property="eventType"
只需告诉jackson要使用的属性名称
然后在JsonSubTypes中我注释了可能的选项,在你的情况2中:
@Type(value = Param1.class, name = "1")
这告诉jackson在事件类型属性为“1”的情况下使用Param1.class
因此,对于PAram2.class和属性值为“2”相同
注意
这就是为什么我稍微改变了json.子类型注释不能将整数作为属性.现在您可以使用不同的选项,例如TypeConverters在运行时将您的整数属性转换为字符串,这样您就可以保持json相同.我跳过了这一步,快速谷歌会给你如何做到这一点的说明.
现在你的参数模型看起来像这样:
public interface Params {
public static class Param1 implements Params {
@JsonProperty
int field1;
}
public static class Param2 implements Params {
@JsonProperty
String field2;
}
}
我正在对这些属性进行注释,因此杰克逊知道要对这些属性进行反序列化.
注意我有一个问题,因为有两个属性让我懒惰的眼睛看起来一样:
JsonTypeInfo.As.EXTERNAL_PROPERTY
JsonTypeInfo.As.EXISTING_PROPERTY
你不能使用现有的:D这需要花费十分钟才能搞清楚.有趣的事实,我上面有两行,并且一直在评论一个,没有理解为什么他们中的一个在另一个工作时抛出异常.
无论如何.
最后测试:
artur@pandaadb:~/tmp/test$curl -XPOST "localhost:8085/api/v2/test" -d @1.json -H "Accept: application/json" -H "Content-Type: application/json"
io.gomedia.resource.Params$Param1
artur@pandaadb:~/tmp/test$
artur@pandaadb:~/tmp/test$curl -XPOST "localhost:8085/api/v2/test" -d @2.json -H "Accept: application/json" -H "Content-Type: application/json"
io.gomedia.resource.Params$Param2
请注意,资源正在打印实例化类的名称.正如您所看到的,两个json已被反序列化为正确的实例类.
我希望有帮助:)
阿图尔
(有趣的事实#2:在我的回答中,我也使用了EXISTING而不是EXTERNAL,只是没有看到它.我可能需要让杰克逊为了我的理智而改变他们的名字)
编辑
我刚尝试过,杰克逊很聪明,可以为你转换你的json.因此,您可以按原样保留json,并将模型中的属性作为String(如图所示).一切正常.
但是为了完整性,如果你想要一个转换器(因为你可能需要将你的字符串模型转换回一个整数来进行serailisation),这将是一个整数到字符串的转换器:
public class EventTypeConverter implements Converter{
@Override
public String convert(Integer value) {
return String.valueOf(value);
}
@Override
public JavaType getInputType(TypeFactory typeFactory) {
return SimpleType.construct(Integer.class);
}
@Override
public JavaType getOutputType(TypeFactory typeFactory) {
return SimpleType.construct(String.class);
}
}
你可以这样做:
@JsonProperty
@JsonDeserialize(converter=EventTypeConverter.class)
String eventType;