使用 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);
}
}
首先,Set
是 a 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();
我有一个 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);
}
}
首先,Set
是 a 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();