使用 Jackson Json 解析格式错误的(?)json 文件

Parsing a malformed(?) json file with Jackson Json

我有一个 JSON file from MTG JSON 是这样设置的:

{
  "data": {
    "10E": {
      ...
    }
    "2ED": {
      ...
    }
    "3ED": {
      ...
    }
    ...
  }
}

data 下的每个对象都是 Set 类型,但它们没有被标记为 Set,而是像您在上面看到的那样被标记 - 带有三个字母设置代码。

我知道我可以做这样的事情:

public class Data {
  @JsonProperty("10E")
  Set x10E;
  
  @JsonProperty("2ED")
  Set x2ED;
}

但我不想按名称对每个集合进行硬编码。相反,我想要一个数组或集合列表。像这样,Jackson 忽略标签并将其视为 Set 对象的数组(或任何其他列表)。

public class Data {
  Set[] sets;
}

有没有办法让 Jackson JSON 进行转换?我当前的主要方法如下所示:

public class AllPrintings {
  Data data;
  public static void main(String[] args) throws Exception {
    byte[] jsonData = Files.readAllBytes(Paths.get("stage/AllPrintings.json"));
    JsonParser parser = new ObjectMapper().readTree(jsonData).traverse();
    ObjectMapper om = new ObjectMapper();
    parser.nextToken();
    om.setVisibility(VisibilityChecker.Std.defaultInstance().withFieldVisibility(Visibility.ANY));
    AllPrintings allPrintings = om.readValue(parser, AllPrintings.class);
  }
}

正如@Tom 在评论中所推荐的,我可以使用注释 @JsonAnySetter 将任何未定义的字段转储到 Map 中:

public class Data {
  Map<String, Set> sets = new HashMap<>();
  
  @JsonAnySetter
  public void setOtherField(String name, Set value) {
    sets.put(name, value);
  }
}

首先,Seta standard built-in Java type 的名称,因此我将使用 MtgSet 以避免使用现有名称造成混淆。

看起来您可能正在解析 JSON:API,在这种情况下,专门处理其结构的库可能会有所帮助。但是,我将在普通的 Jackson 中展示如何做到这一点。

首先,我们将定义一个包装器 class 来匹配您的根 JSON:

class AllPrintings {
  Map<String, MtgSet> data;
}

您的 Jackson 调用有点过于复杂,我们可以简化。

var is = new FileInputStream("stage/AllPrintings.json"); // just open it directly
Map<String, MtgSet> sets = new ObjectMapper()
  .readValue(is, AllPrintings.class) // no need to explicitly mess with parser instances
  .data; // pull the wrapped value out of the wrapper class
is.close();