我正在使用RestTemplate消费一个“RESTful”服务,它产生以下JSON:
{
"id": "abcd1234",
"name": "test",
"connections": {
"default": "http://foo.com/api/",
"dev": "http://dev.foo.com/api/v2"
},
"settings": {
"foo": "{\n \"fooId\": 1, \"token\": \"abc\"}",
"bar": "{\"barId\": 2, \"accountId\": \"d7cj3\"}"
}
}
请注意
settings.foo
和settings.bar
的值,这会在反序列化过程中引起问题。我希望能够将其反序列化为对象(例如:settings.getFoo().getFooId()
,settings.getFoo().getToken()
)。
我已经为Foo
的一个实例编写了自定义反序列化器,以解决这个问题。
public class FooDeserializer extends JsonDeserializer<Foo> {
@Override
public Foo deserialize(JsonParser jp, DeserializationContext ctx) throws IOException {
JsonNode node = jp.getCodec().readTree(jp);
String text = node.toString();
String trimmed = text.substring(1, text.length() - 1);
trimmed = trimmed.replace("\\", "");
trimmed = trimmed.replace("\n", "");
ObjectMapper mapper = new ObjectMapper();
JsonNode obj = mapper.readTree(trimmed);
Foo result = mapper.convertValue(obj, Foo.class);
return result;
}
}
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Settings {
@JsonDeserialize(using = FooDeserializer.class)
private Foo foo;
private Bar bar;
}
然而,现在如果我想反序列化settings.bar
,我需要再实现另一个自定义反序列化器。因此,我实现了一个通用的反序列化器如下:
public class QuotedObjectDeserializer<T> extends JsonDeserializer<T> implements ContextualDeserializer {
private Class<?> targetType;
private ObjectMapper mapper;
public QuotedObjectDeserializer(Class<?> targetType, ObjectMapper mapper) {
this.targetType = targetType;
this.mapper = mapper;
}
@Override
public JsonDeserializer<T> createContextual(DeserializationContext context, BeanProperty property) {
this.targetType = property.getType().containedType(1).getRawClass();
return new QuotedObjectDeserializer<T>(this.targetType, this.mapper);
}
@Override
public T deserialize(JsonParser jp, DeserializationContext context) throws IOException {
JsonNode node = jp.getCodec().readTree(jp);
String text = node.toString();
String trimmed = text.substring(1, text.length() - 1);
trimmed = trimmed.replace("\\", "");
trimmed = trimmed.replace("\n", "");
JsonNode obj = this.mapper.readTree(trimmed);
return this.mapper.convertValue(obj, this.mapper.getTypeFactory().constructType(this.targetType));
}
}
现在我不确定如何实际使用反序列化器,因为显然将Settings.Foo
注释为@JsonDeserialize(using = QuotedObjectDeserializer.class)
是无效的。
有没有一种方法可以注释属性以使用通用自定义反序列化器?或者更可能的是,有没有一种方法可以配置默认的反序列化器来处理我的示例JSON中返回的字符串对象?
编辑:这里的问题特别在于将settings.foo
和settings.bar
反序列化为对象。JSON表示形式将这些对象包装在引号中(并且污染了转义序列),因此它们被反序列化为Strings
。