【问题标题】:RestTemplate - Jackson DeserializerRestTemplate - 杰克逊反序列化器
【发布时间】:2016-10-23 15:52:33
【问题描述】:

我正在尝试使用 RestTemplate 使用 REST 服务。我在反序列化 JSON 响应时遇到问题。我正在使用自定义解串器,我的 JSON 有 3 个节点,但看起来只有一个节点到达解串器。以下是更多详细信息。

以下是响应 JSON:

{
    "Hello": {
        "Hi": "Name1",
        "Call": "PhoneNumber1"
    },
    "Hello": {
        "Hi": "Name2",
        "Call": "PhoneNumber2"
    },
    "Hello": {
        "Hi": "Name3",
        "Call": "PhoneNumber3"
    }
}

我正在使用 @JsonDeserializer 在属性 Hello 的响应类上使用自定义反序列化器。

当我执行如下 readTree 时:

JsonNode node = jp.getCodec().readTree(jp);

它到达了反序列化方法,看起来它只有一个节点而不是下面的 3 个节点。有时它具有第一个节点,有时具有最后一个节点。这里可能出了什么问题?

提前感谢您查看此问题并提供帮助!

回答: 正如其他人所提到的,这个 JSON 是无效的,因此杰克逊无法反序列化它。我必须将响应作为字符串获取,然后手动反序列化。

【问题讨论】:

    标签: jackson json-deserialization


    【解决方案1】:

    JsonNode 是一个没有特定内容行为的超类。在您的示例中,您应该得到一个ObjectNode,但由于您的属性都具有相同的名称,因此只会保留一个“Hello”属性。 readTree() 是一种通用方法,如果可能,它会自动转换为您需要的返回类型。

    如果你真的需要这个,你必须将你的 JSON 移动到一个数组结构中:

    // you will get one ArrayNode containing multiple ObjectNode
    [
      {
        "Hello": {
          "Hi": "Name1",
          "Call": "PhoneNumber1"
        }
      },
      {
        "Hello": {
          "Hi": "Name2",
          "Call": "PhoneNumber2"
        }
      },
      {
        "Hello": {
          "Hi": "Name3",
          "Call": "PhoneNumber3"
        }
      }
    ]
    

    // you will get one ObjectNode containing one property with an ArrayNode
    {
      "Hello": [
        {
          "Hi": "Name1",
          "Call": "PhoneNumber1"
        },
        {
          "Hi": "Name2",
          "Call": "PhoneNumber2"
        },
        {
          "Hi": "Name3",
          "Call": "PhoneNumber3"
        }
      ]
    }
    

    【讨论】:

    • 我正在使用一项服务,该服务目前存在于生产环境中,并且正在其他地方使用。我可以在收到响应后将 JSON 转换为数组吗?
    • 抱歉,这对 Jackson imho 永远不起作用,因为 ObjectNode 被认为具有唯一键。
    • 这样做的唯一方法是完全自定义反序列化器,不使用树方法,而是使用getCurrentToken()get...Value()nextToken() 进行解析。将其解析为列表或多地图类型。工作量很大,但最终还是可以工作的。
    • 你说的是真的。但我最终没有获取令牌,而是使用正则表达式来收集响应字符串中的每个节点,然后在每个收集的节点上使用 ObjectMapper,这是一个有效的 JSON 将其脱轨到 POJO。
    【解决方案2】:

    这很可能是因为那是无效的 JSON,您不能拥有三个具有相同名称的节点。

    或者严格来说这不是一个错误,但只有一个名为 “Hello” 的项目将被占用as stated in this answer,这很糟糕,因为 json 不保证项目中项目的顺序仅反对列表中项目的顺序。

    如果您有可能更改响应,我会改为创建一个对象数组。

    { "Hello": [ { "Hi": "Name1", "Call": "PhoneNumber1" }, { "Hi": "Name2", "Call": "PhoneNumber2" }, { "Hi": "Name3", "Call": "PhoneNumber3" } ] } 然后你会得到一个 JsonNode,它是一个 JsonNode 数组,你可以对其进行迭代。

    【讨论】:

    • 我正在使用一项服务,该服务目前存在于生产环境中,并且正在其他地方使用。我可以在收到响应后将 JSON 转换为数组吗?
    • 也许这个答案可以帮助你:stackoverflow.com/questions/27710471/…,请务必阅读那里的 cmets :)
    • 谢谢@Daniel,我会试试 Guava 并在这里更新它。
    猜你喜欢
    • 2015-04-07
    • 1970-01-01
    • 2012-09-10
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多