java反序列化防御规则_java – 泽西州解析JSON / Jackson子类型反序列化的规则

今天早上我花了一些时间来解决这个问题.一个有趣的用例.我想出了怎么做,但我不得不稍微改变你的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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值