如何配置 Jackson ObjectMapper 以将 Foo 类型的所有字段反序列化为 SubclassOfFoo 的实例?
How do I configure Jackson ObjectMapper to deserialize all fields of type Foo into instances of SubclassOfFoo?
我正在反序列化一个很大的 json 值。深度嵌套在该值中的是一个 json 对象,如下所示:
{
"fieldOne": "valueOne",
"fieldTwo": {
"innerField": "innerValue"
}
}
我正在使用 Jackson ObjectMapper
将较大的 json 值反序列化为第 3 方 class。深深嵌套在第 3 方 class 中的是另一个第 3 方 class:
public class DeepThirdPartyClass {
public String fieldOne;
}
不幸的是缺少 fieldTwo
属性。我可以创建自己的 class 来添加缺少的字段:
public class MyClass extends DeepThirdPartyClass {
public MySubObject fieldTwo;
}
如何配置 jackson,以便每当它尝试将值反序列化为 DeepThirdPartyClass
时,它反序列化为 MyClass
?
当我必须过滤所有字符串值中任何不允许的字符时,我有类似的要求。
创建对象映射器:
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper() {
super();
SimpleModule module = new SimpleModule("HTML XSS Serializer", new Version(1, 0, 0, "FINAL", "com.crowdoptic", "web"));
module.addSerializer(String.class, new JsonHtmlXssSerializer());
module.addDeserializer(String.class, new JsonHtmlXssDeserializer());
this.registerModule(module);
}
}
public class JsonHtmlXssDeserializer extends StdScalarDeserializer<String> {
private static final Logger LOG = LogManager.getLogger(JsonHtmlXssDeserializer.class);
public JsonHtmlXssDeserializer() { super(String.class); }
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = StringDeserializer.instance.deserialize(p, ctxt);
LOG.trace("in deserialize for value: " + value);
String encodedValue = StringEscapeUtils.escapeHtml4(value);
return encodedValue;
}
@Override
public String deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
return StringDeserializer.instance.deserializeWithType(jp, ctxt, typeDeserializer);
}
@Override
public boolean isCachable() { return StringDeserializer.instance.isCachable(); }
}
在您的情况下,您可以注册 class 反序列化器,调用对象反序列化器的超级方法。然后不返回 DeepThirdPartyClass,而是创建 MyClass 的对象,从 DeepThirdPartyClass 设置第一个字段并添加第二个字段。请参阅 StringDeserializer 和其他实现细节和可用属性。
如果有帮助请告诉我。
我修改了@olga-khylkouskaya 的解决方案以解决我的问题:
@Test
public void newDeserializer() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule("DeepThirdPartyClass subclass override", new Version(1, 0, 0, "FINAL", "com.example", "deep-third-party-class-override"));
module.addDeserializer(DeepThirdPartyClass.class, new JsonDeserializer<DeepThirdPartyClass>() {
@Override
public DeepThirdPartyClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return p.readValueAs(MyClass.class);
}
});
objectMapper.registerModule(module);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
String json = "{\n" +
" \"middle\": {\n" +
" \"fieldOne\": \"valueOne\",\n" +
" \"fieldTwo\": {\n" +
" \"fieldThree\": \"valueThree\"\n" +
" }\n" +
" }\n" +
"}\n";
ThirdPartyClass thirdPartyClass = objectMapper.readValue(json, ThirdPartyClass.class);
}
public class ThirdPartyClass {
public DeepThirdPartyClass middle;
}
public class InnerClass {
public String fieldThree;
}
我正在反序列化一个很大的 json 值。深度嵌套在该值中的是一个 json 对象,如下所示:
{
"fieldOne": "valueOne",
"fieldTwo": {
"innerField": "innerValue"
}
}
我正在使用 Jackson ObjectMapper
将较大的 json 值反序列化为第 3 方 class。深深嵌套在第 3 方 class 中的是另一个第 3 方 class:
public class DeepThirdPartyClass {
public String fieldOne;
}
不幸的是缺少 fieldTwo
属性。我可以创建自己的 class 来添加缺少的字段:
public class MyClass extends DeepThirdPartyClass {
public MySubObject fieldTwo;
}
如何配置 jackson,以便每当它尝试将值反序列化为 DeepThirdPartyClass
时,它反序列化为 MyClass
?
当我必须过滤所有字符串值中任何不允许的字符时,我有类似的要求。 创建对象映射器:
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper() {
super();
SimpleModule module = new SimpleModule("HTML XSS Serializer", new Version(1, 0, 0, "FINAL", "com.crowdoptic", "web"));
module.addSerializer(String.class, new JsonHtmlXssSerializer());
module.addDeserializer(String.class, new JsonHtmlXssDeserializer());
this.registerModule(module);
}
}
public class JsonHtmlXssDeserializer extends StdScalarDeserializer<String> {
private static final Logger LOG = LogManager.getLogger(JsonHtmlXssDeserializer.class);
public JsonHtmlXssDeserializer() { super(String.class); }
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = StringDeserializer.instance.deserialize(p, ctxt);
LOG.trace("in deserialize for value: " + value);
String encodedValue = StringEscapeUtils.escapeHtml4(value);
return encodedValue;
}
@Override
public String deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
return StringDeserializer.instance.deserializeWithType(jp, ctxt, typeDeserializer);
}
@Override
public boolean isCachable() { return StringDeserializer.instance.isCachable(); }
}
在您的情况下,您可以注册 class 反序列化器,调用对象反序列化器的超级方法。然后不返回 DeepThirdPartyClass,而是创建 MyClass 的对象,从 DeepThirdPartyClass 设置第一个字段并添加第二个字段。请参阅 StringDeserializer 和其他实现细节和可用属性。
如果有帮助请告诉我。
我修改了@olga-khylkouskaya 的解决方案以解决我的问题:
@Test
public void newDeserializer() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule("DeepThirdPartyClass subclass override", new Version(1, 0, 0, "FINAL", "com.example", "deep-third-party-class-override"));
module.addDeserializer(DeepThirdPartyClass.class, new JsonDeserializer<DeepThirdPartyClass>() {
@Override
public DeepThirdPartyClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return p.readValueAs(MyClass.class);
}
});
objectMapper.registerModule(module);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
String json = "{\n" +
" \"middle\": {\n" +
" \"fieldOne\": \"valueOne\",\n" +
" \"fieldTwo\": {\n" +
" \"fieldThree\": \"valueThree\"\n" +
" }\n" +
" }\n" +
"}\n";
ThirdPartyClass thirdPartyClass = objectMapper.readValue(json, ThirdPartyClass.class);
}
public class ThirdPartyClass {
public DeepThirdPartyClass middle;
}
public class InnerClass {
public String fieldThree;
}