忽略"Can not deserialize instance of java.util.LinkedHashMap out of START_ARRAY token"错误



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

无论如何,所以正在发生的事情是 JSON 响应中的一个字段主要是地图,但有时,突然它是一个列表。

例如,假设以下是我通常得到的响应:

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

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

例如:

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

我正在使用杰克逊将此响应映射到POJO。在违反合同的情况下,我得到错误,

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

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

我知道@JsonIgnoreProperties(忽略未知=真),但这总是会忽略minorInfo字段。我只希望在字段不遵守合同时忽略它。这可能吗?

我也试过

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 

但这也没有用。

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

谢谢

编辑:一种解决方案是我为两种变体都有一个 POJO,并将代码放在 try catch 块中。如果 JSON 响应只有一个违反协定的字段并且仅以一种特定方式,则可能会起作用。我实际上得到的回应是巨大的,这是我在第三个领域发现的第三次违规行为。我不能继续放置尝试捕获块,到第三次违规时,我意识到最好的选择是忽略违反它的字段。

我使用以下线程作为参考找到了解决方案:Jackson:忽略属性而不是抛出 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;
    }
}

您可以编写自己的 java 方法,将输入 json 转换为遵守合约的"标准"json,然后在其上使用 Jackson。

大致如下:

private String transform(String input)
{
    String result = input;
    if (result.contains(""minorInfo" : []"))
    {
        result = result.replace(""minorInfo" : []", "");
    }
    return result;
}

相关内容

最新更新