【问题标题】:RestTemplate & Jackson - Custom JSON deserializing?RestTemplate & Jackson - 自定义 JSON 反序列化?
【发布时间】:2013-01-18 16:20:23
【问题描述】:

网络服务返回一个空字符串而不是导致 Jackson 崩溃的 NULL。 所以我创建了一个自定义解析器,我试图手动解析它?知道如何实现吗?

我在这里做错了什么?我要做的就是像往常一样将 JSON 解析为对象。使用 @JsonProperty 将字段名称添加到我的属性中,因此解析器应该知道如何转换它。

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;
    }

}

【问题讨论】:

    标签: java json jackson resttemplate


    【解决方案1】:

    我不确定您是否需要手动解析响应。您的解决方案会起作用,但在我看来似乎不是最理想的。由于看起来您正在使用 RestTemplate,因此您应该编写(或将解析器代码移动到)您自己的消息转换器。然后将此转换器添加到您的其余模板对象中,该对象将在内部为您反序列化该值。有点像,

    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);
    

    【讨论】:

    • 在大多数情况下,我不必对反序列化做任何事情,这是一种特殊情况,其中不良数据来自导致解析崩溃的服务器,因为解析器需要一个对象结构,但响应是一个空字符串(用于结果中的特定字段)。因此,这是一种仅反序列化我的应用程序中的一个模型的解决方法。在应用程序的其余部分中,我不需要做任何事情来反序列化 JSON,这一切都由 RestTemplate 和 Jackson 自动化(使用 @JsonProperty 注释)。
    • 没错,所以我上面的解决方案建议你将这个特殊的转换器添加到你的 rest 模板中,它将处理空的响应字符串,从而消除手动反序列化。提供转换器以准确处理此类情况
    • 哦,所以不是在单个类反序列化中处理错误,而是将其移至 MessageConverter,然后将其应用于所有内容。我会试一试,然后会回复
    • 你明白了。看看 MappingJackson2HttpMessageConverter 源码。您希望将所有方法保留在自定义转换器中,与 MappingJackson2HttpMessageConverter 完全相同,但使用您的代码/或我上面的代码覆盖 readInternal()。反序列化对象时调用来自适当转换器的 readInternal()(由 rest 模板根据响应 Content-Type 选择)。
    【解决方案2】:

    我是这样解决的

    @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;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-01-29
      • 2011-04-12
      • 2021-06-22
      • 2014-08-02
      • 2013-10-10
      • 1970-01-01
      • 2019-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多