Java 如何反序列化此json

Java 如何反序列化此json,java,json,jackson,Java,Json,Jackson,这是MediaWiki API返回的json响应。我想创建一个类,以便能够使用Jackson库对其进行反序列化。问题是这个json包含一个不同于每个请求的键(这里是290) 如何创建一个类(或配置映射器)来反序列化这个json?这看起来像是一对键值。 您可以使用map来反序列化键值对: public class Query { private Map<Integer, Page> pages; public Map<Integer, Page> getPa

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


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

这看起来像是一对键值。 您可以使用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;
   }
}
公共类查询{
私人地图页;
公共地图getPages(){
返回页面;
}
公共无效设置页(地图页){
this.pages=页面;
}
}

默认情况下,Jackson会处理这种反序列化。

简单的回答是,你不能,至少在当前格式中,这个讨厌的星号不存在。因此,我们将不得不在这里雇佣一些黑客来完成这项工作,我预先警告你,这将不会很好

首先,复制该响应,然后转到并将其粘贴到JSON文本框中。粘贴后,将星号更改为更文明的内容,如“内容”。选择JSON(默认为JSON模式)作为源类型,分别输入包和根类名,然后单击JAR生成包含映射到此JSON的所有POJO的包。您还可以单击“预览”并将代码复制粘贴到源文件中——这完全取决于您自己

现在我们有了这个JSON结构的有效版本,我们使用Jackson来读取它。如果您的JSON字符串名为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_属性设置为false,这意味着它将忽略该星号,并为您创建其他所有内容

现在,为了实际获取该星号存在的任何值并将其存储到我们的“content”属性中(或者您希望用任何其他内容替换该星号),您必须解析这个吸盘并将其作为单独的输入参数传递,然后执行此操作,您必须通过以下方式将其拔出:

var content = query.pages.290.revisions["*"];
此内容参数将被传递并存储到POJO的内容属性中


我知道这是一个很大的工作,如果其他人有一个更优雅的解决方案,请分享。正如我所说,我的不会很漂亮。:-)

您可以使用Jackson将JSON反序列化为多种格式。您提到的一种方法是将JSON转换为POJO,当键是动态的时,这可能会很困难。另一种方法是将JSON反序列化到Jackson树模型,该模型称为
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-json注释@JsonProperty(“*”)字符串星号轻松解析;不是真的。当试图将星号转换为实际的Java变量名时,星号是一个很大的问题,因为*是一个保留的Java关键字。换句话说,Java类中不能有一个名为*的字符串,这就是为什么如果按原样复制JSON响应并尝试在上生成POJO类,则会出现一个内部服务器错误。我同意Java中不能有名为*的变量。这就是我提到的杰克逊注释的原因。这样,您不需要在JavaPOJO中为变量命名“*”,但您可以给它取任何您喜欢的名称。您提到的Jsonschema2pojo.org POJO生成器是一个有限的工具,显然不能处理此类情况。您提供的解决方案比只向字段添加注释要复杂得多。@extraleon,没错。说得好!。OP:s的问题是解析“动态字段”,比如“290”。啊,我现在明白你的意思了。如果我们将@JsonProperty(“*”)添加到内容变量(或您想调用它的任何其他变量),则该值将转换,无需执行我答案的第二部分。虽然,正如@wassgren所提到的,这是解析动态键的问题,所以阻力最小的方法是使用Jackson树模型,尽管这需要通过节点进行大量迭代。是的,这是一个很好的建议,这肯定是另一种方法。他还可以结合我们的方法,按照我描述的方式创建POJO,然后使用您的建议只查询*内容并将其设置到POJO中。@尽管如此,如果您使用
@JsonProperty(“*”
),星号不是问题。问题在于解析动态数据时,您实际上不知道属性名称(示例中为“290”)。您自己和@extraleon做了很好的工作和解释。尽管@wassgren的解决方案是有效的,但我认为从呈现的json格式和字段命名可以推断字段“pages”就像一个格式的关联数组{“dynamic page id”:“static typed page object”,…}。在本例中,使用“pages”字段的映射创建POJO似乎比在JsonNodes树上迭代更简单。@extraleon Ageed,一个带有动态页面字段的POJO。只是想说明
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
}