如何反序化这个json

时间:2015-01-18 15:58:26

标签: java json jackson

这是MediaWiki API返回的json响应。我想创建一个类,以便能够将其反序列化为使用Jackson库。问题是这个json包含一个与每个请求不同的密钥(这里是290)。

{
    "query-continue": {
        "revisions": {
            "rvcontinue": 633308090
        }
    },
    "query": {
        "pages": {
            "290": {
                "pageid": 290,
                "ns": 0,
                "title": "A",
                "revisions": [
                    {
                        "user": "Mr. Guye",
                        "timestamp": "2014-12-07T17:45:55Z",
                        "comment": "comment",
                        "contentformat": "text/x-wiki",
                        "contentmodel": "wikitext",
                        "*": "content"
                    }
                ]
            }
        }
    }
}

如何创建一个类(或配置映射器)以便能够反序列化这个json?

3 个答案:

答案 0 :(得分:2)

您可以使用Jackson将JSON反序列化为多种格式。您提到的一种方法是将JSON转换为POJO,当密钥是动态的时,这可能很难。另一种方法是将JSON反序列化为杰克逊树模型,称为JsonNode。以下说明了如何将提供的JSON解析为JsonNode,然后检索各种属性。

final ObjectMapper mapper = new ObjectMapper();

// Parse the JSON, deserialize to the Tree Model
final JsonNode jsonNode = mapper.readTree(jsonString);

// Get hold of the "query -> pages" node.
final JsonNode pages = jsonNode.path("query").path("pages");

// Iterate the pages
for (final JsonNode page : pages) {
    // Work with the page object here...
    System.out.println(page.get("pageid")); // -> 290
}

JsonNode对象非常灵活,包含用于访问数据的各种便利功能。如上例所示,path()get()方法是两种访问数据的方法。如果使用get()属性必须存在,如果使用path属性可能存在。此外,有多种方法可以迭代子元素,上面显示的循环是单向的。

请查看Jackson docs了解详情。

答案 1 :(得分:0)

简短的回答是你不能,至少不是当前格式存在那个可恶的星号。因此,我们将不得不在这里使用一些hackery来完成工作,我提前警告你,它不会很漂亮。

首先,复制该响应,然后转到http://www.jsonschema2pojo.org/并将其粘贴到JSON文本框中。粘贴后,将星号更改为更文明的内容,例如"内容"。为源类型选择JSON(默认为JSON Schema),分别输入包和根类名,然后单击JAR以生成包含映射到此JSON的所有POJO的包。您也可以点击"预览"并将代码复制粘贴到源文件中 - 这完全取决于您。

现在我们有了这个JSON结构的有效版本,我们使用Jackson来读取它。如果你的JSON String被称为jsonResponse并且相应的POJO类是MediaWiki,那么你用Jackson将它转换成这样:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MediaWiki mw = objectMapper.readValue(profileJson, MediaWiki.class);

这里的关键是将FAIL_ON_UNKNOWN_PROPERTIES设置为false,这意味着它将忽略该星号,并为您创建其他所有内容。

现在,要实际抓住该星号的任何值,并将其存储到我们的内容中#34;属性(或任何你想要的替换星号的东西),你将不得不在客户端解析这个sucker并将其作为一个单独的输入参数传递,为此,你必须通过调用某些东西来解决它像这样:

var content = query.pages.290.revisions["*"];

传递此内容参数并将其存储到您的POJO内容属性中。

我知道它做了很多工作,如果其他人有更优雅的解决方案,请分享。正如我所说,我的不是很漂亮。 : - )

答案 2 :(得分:-1)

这看起来像键值对。 您可以使用map来反序列化键值对:

public class Query {

   private Map<Integer, Page> pages;

   public Map<Integer, Page> getPages() {
      return pages;
   }

   public void setPages(Map<Integer, Page> pages) {
      this.pages = pages;
   }
}
杰克逊默认处理这种反序列化。