忽略“无法从START_ARRAY令牌中反序列化java.util.LinkedHashMap的实例”错误

时间:2016-02-23 10:25:45

标签: java json rest jackson

我正在使用外部合作伙伴的API。不幸的是,返回的响应似乎没有固定的结构。理想情况下,API合约意味着它不会被违反,但这种情况一直在发生。

无论如何,所发生的事情是JSON响应中的一个字段主要是一个映射,但有时候,它是一个列表。

例如,假设以下是我通常得到的回复:

{
  "majorInfo" : {
    "a" : "b"
  },
  "minorInfo" : {
    "c" : "d"
  }
}

但在极少数情况下,我会得到一份清单,而不是地图或其他违反合同的内容。

例如:

{
  "majorInfo" : {
    "a" : "b"
  },
  "minorInfo" : []
}

我正在使用jackson将此回复映射到POJO。如果违反合同,我会收到错误

  

线程“main”中的异常   com.fasterxml.jackson.databind.JsonMappingException:不能   从START_ARRAY反序列化java.util.LinkedHashMap的实例   令牌

在这种情况下,即使遵守合同,我也会丢失majorInfo字段中的信息。有什么方法可以在不遵守合同时忽略某个领域?在这种情况下,我的POJO的majorInfo成员将被正确设置,但minorInfo成员将为null。

我知道@JsonIgnoreProperties(ignoreUnknown = true)但总是忽略minorInfo字段。当该领域不遵守合同时,我只想忽略它。这可能吗?

我也试过

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 

但这也不起作用。

还有其他解决方案吗?外部合作伙伴不会为我们更改他们的API,这是肯定的。那么,我们最终的任何可行的解决方案呢?

谢谢

编辑: 一个解决方案是我有两个变量的POJO并将代码放在try catch块中。如果JSON响应只有一个违反合同的字段并且只有一种特定的方式,那么这可能有效。我实际上得到的回应是巨大的,这是我在第三场比赛中遇到的第三次违规。我不能继续尝试使用try catch块,并且通过第三次违规,我意识到最好的办法是忽略违反它的字段。

2 个答案:

答案 0 :(得分:3)

我找到了使用以下线程作为参考的解决方案: Jackson: ignoring properties instead of throwing JsonMappingException

我写了一个自定义反序列化器并用它来忽略错误。

public class CustomListingDeserializer extends JsonDeserializer<Map<String, Listing>>{

    public CustomListingDeserializer() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public Map<String, Listing> deserialize(JsonParser arg0, DeserializationContext arg1)
            throws IOException, JsonProcessingException {

        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = arg0.readValueAsTree();

        try
        {
            return mapper.readValue(node.toString(), new TypeReference<Map<String,Listing>>(){});

        }
        catch (JsonMappingException e)
        {
            System.out.println("Issue in deserializing : " + e.getMessage() + "for :" + node.toString());
        }
        catch (Exception e)
        {
            throw e;
        }
        // TODO Auto-generated method stub
        return null;
    }

}

答案 1 :(得分:1)

您可以编写自己的java方法,将输入json转换为符合合同的“标准”json,然后在其上使用Jackson。

类似于:

private String transform(String input)
{
    String result = input;

    if (result.contains("\"minorInfo\" : []"))
    {
        result = result.replace("\"minorInfo\" : []", "");
    }

    return result;
}