Java rest模板&;Jackson-自定义JSON反序列化?
webservice返回一个空字符串,而不是导致Jackson崩溃的NULL。 所以我创建了一个自定义解析器,并尝试手动解析它?你知道我怎样才能做到这一点吗 我做错了什么?我所要做的就是像平常一样将JSON解析为object。字段名使用@JsonProperty添加到我的属性中,因此解析器应该知道如何转换它Java rest模板&;Jackson-自定义JSON反序列化?,java,json,jackson,resttemplate,Java,Json,Jackson,Resttemplate,webservice返回一个空字符串,而不是导致Jackson崩溃的NULL。 所以我创建了一个自定义解析器,并尝试手动解析它?你知道我怎样才能做到这一点吗 我做错了什么?我所要做的就是像平常一样将JSON解析为object。字段名使用@JsonProperty添加到我的属性中,因此解析器应该知道如何转换它 public class InsertReplyDeserializer extends JsonDeserializer<ListingReply> { @Overr
public class InsertReplyDeserializer extends JsonDeserializer<ListingReply> {
@Override
public ListingReply deserialize(JsonParser jsonParser, DeserializationContext arg1)
throws IOException, JsonProcessingException {
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
// If service returns "" instead of null return a NULL object and don't try to parse
if (node.getValueAsText() == "")
return null;
ObjectMapper objectMapper = new ObjectMapper();
ListingReply listingReply = objectMapper.readValue(node, ListingReply.class);
return listingReply;
}
}
公共类InsertReplyDeserializer扩展JsonDeserializer{
@凌驾
public ListingReply反序列化(JsonParser JsonParser,反序列化上下文arg1)
抛出IOException、JsonProcessingException{
ObjectCodec oc=jsonParser.getCodec();
JsonNode=oc.readTree(jsonParser);
//如果服务返回“”而不是null,则返回null对象,并且不尝试解析
如果(node.getValueAsText()=“”)
返回null;
ObjectMapper ObjectMapper=新的ObjectMapper();
ListingReply ListingReply=objectMapper.readValue(节点,ListingReply.class);
返回列表回复;
}
}
以下是我解决问题的方法
@Override
public MyObject deserialize(JsonParser jsonParser, DeserializationContext arg1)
throws IOException, JsonProcessingException {
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
if (node.getValueAsText() == "")
return null;
MyObject myObject = new MyObject();
myObject.setMyStirng(node.get("myString").getTextValue());
JsonNode childNode = node.get("childObject");
ObjectMapper objectMapper = new ObjectMapper();
ChildObject childObject = objectMapper.readValue(childNode,
ChildObject.class);
myObject.setChildObject(childObject);
return myObject;
}
我不确定您是否需要手动解析响应。你的解决方案会起作用,但在我看来似乎是次优的。因为看起来您正在使用RestTemplate,所以应该编写(或将解析器代码移动到)您自己的消息转换器。然后将此转换器添加到rest模板对象,该对象将在内部为您反序列化该值。沿着这条路线
public class CustomHttpmsgConverter extends AbstractHttpMessageConverter<Object> {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
InputStream istream = inputMessage.getBody();
String responseString = IOUtils.toString(istream);
if(responseString.isEmpty()) //if your response is empty
return null;
JavaType javaType = getJavaType(clazz);
try {
return this.objectMapper.readValue(responseString, javaType);
} catch (Exception ex) {
throw new HttpMessageNotReadableException(responseString);
}
}
//add this converter to your resttemplate
RestTemplate template = new RestTemplate();
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(new CustomHttpmsgConverter());
template.setMessageConverters(converters);
公共类CustomHttpmsgConverter扩展了AbstractHttpMessageConverter{
私有ObjectMapper ObjectMapper=新ObjectMapper();
@凌驾
受保护的对象readInternal(类clazz,HttpInputMessage inputMessage)引发IOException,HttpMessageGenetradableException{
InputStream istream=inputMessage.getBody();
字符串responseString=IOUtils.toString(istream);
if(responseString.isEmpty())//如果您的响应为空
返回null;
JavaType JavaType=getJavaType(clazz);
试一试{
返回this.objectMapper.readValue(responseString,javaType);
}捕获(例外情况除外){
抛出新的HttpMessageTreadableException(responseString);
}
}
//将此转换器添加到resttemplate
RestTemplate=新的RestTemplate();
列表>();
添加(新的CustomHttpmsgConverter());
模板.setMessageConverters(转换器);
在大多数情况下,我不必做任何关于反序列化的事情,这是一种特殊情况,即坏数据来自服务器,导致解析崩溃,因为解析器需要对象结构,但响应是空字符串(对于结果中的特定字段)。因此,这是一个仅对我应用程序中的一个模型进行反序列化的变通方法。在应用程序的其余部分,我不必做任何事情来反序列化JSON,它都由RestTemplate&Jackson(使用@JsonProperty注释)自动执行。正是这样,我上面的解决方案建议您将此特殊转换器添加到rest模板中,该模板将处理空响应字符串,从而消除手动反序列化。提供转换器的目的是准确地处理OOH这样的情况,因此您可以将其移到MessageConverter,然后将应用于所有内容。我会尝试一下,并将其发回给您。请查看MappingJackson2HttpMessageConverter源代码。您希望保留自定义转换器中的所有方法,与MappingJackson2HttpMessageConverter完全相同,但使用上面的代码/或我的代码重写readInternal()。readInternal()当反序列化对象时,从相应的转换器(由rest模板根据响应内容类型选择)调用。