我有一个下面的JSON,我需要根据它创建一个Map<String, String>
。在下面的JSON中,我只有三个级别的parentCategory
,但通常它可以更大或更小。
我地图的键将是79720
,这是id
部分的categories
,值应该是10987
,是最后一个id
的parentCategory
。
现在我可以在其中嵌套parentCategory
,因此在为此创建POJO时遇到问题。我可以有一个级别parentCategory
,也可以在每个parentCategory
内嵌套parentCategory
,而我总是需要获取最后一个parentCategory
的ID。
因此,我通过转到jsonschema2pojo为此创建一个POJO,并提供了JSON,它在其中生成了我所需的所有文件。使用以下JSON,它为ParentCategory
字段创建了三个类,例如ParentCategory_
,ParentCategory__
和parentCategory
。现在,由于我不知道我有多少parentCategory
个级别,因此我不确定为他们生成POJO并为最后一个id
提取parentCategory
字段的最佳方法是什么。有没有办法用杰克逊做到这一点?
我必须在POJO中读取所有这些数据,因为我也在读取所有其他字段。
{
"paginationResponse": {
"pageNumber": 1,
"entriesPerPage": 200,
"totalPages": 3
},
"listings": [
{
"categories": [
{
"id": "79720",
"name": "Sunglasses",
"localizedName": "Sunglasses",
"level": 4,
"leafCategory": true,
"parentCategory": {
"id": "394",
"name": "Sunglasses & Fashion Eyewear",
"localizedName": "Sunglasses & Fashion Eyewear",
"level": 3,
"leafCategory": false,
"parentCategory": {
"id": "2340",
"name": "Men's Accessories",
"localizedName": "Men's Accessories",
"level": 2,
"leafCategory": false,
"parentCategory": {
"id": "10987",
"name": "Clothing, Shoes & Accessories",
"localizedName": "Clothing, Shoes & Accessories",
"level": 1,
"leafCategory": false
}
}
}
}
],
"processlisting": {
....
},
"processlistingmetainfo": {
...
},
"processlistingproperties": [
{
"propertyName": "item_url",
"propertyValues": [
{
"stringValue": "url"
}
]
},
{
"propertyName": "listing_site_id",
"propertyValues": [
{
"stringValue": "0"
}
]
}
]
}
],
"total": 100
}
注意:我无法控制此JSON结构,因为它不归我们所有,因此根本无法更改JSON结构。
以下是
ParentCategory
的三个类,它们是根据上述JSON生成的,但总的来说,我可以具有多个ParentCategory
级别,而我事先并不知道。public class ParentCategory {
@JsonProperty("id")
private String id;
@JsonProperty("name")
private String name;
@JsonProperty("localizedName")
private String localizedName;
@JsonProperty("level")
private long level;
@JsonProperty("leafCategory")
private boolean leafCategory;
@JsonProperty("parentCategory")
private ParentCategory_ parentCategory;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
....
}
public class ParentCategory_ {
@JsonProperty("id")
private String id;
@JsonProperty("name")
private String name;
@JsonProperty("localizedName")
private String localizedName;
@JsonProperty("level")
private long level;
@JsonProperty("leafCategory")
private boolean leafCategory;
@JsonProperty("parentCategory")
private ParentCategory__ parentCategory;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
...
}
public class ParentCategory__ {
@JsonProperty("id")
private String id;
@JsonProperty("name")
private String name;
@JsonProperty("localizedName")
private String localizedName;
@JsonProperty("level")
private long level;
@JsonProperty("leafCategory")
private boolean leafCategory;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
...
}
最佳答案
一般而言-检索特定JSON属性的最佳工具是Json-Path,它提供了丰富的查询语言来搜索JSON树。
关于该问题,需要检索两个不相关的属性,因此需要对JSON树进行两次扫描。该问题未指定如何读取输入,因此也许可以将整个输入流读取为一个String。
下面是带有检索这两个属性所需的查询的代码。不管parentCategory
级别的数量如何,它都将起作用。诀窍是最后一个对象是唯一没有子对象parentCategory
的对象。
我已经在解释查询文本的代码中添加了注释
String categoryIdJsonPath =
"$" + // start from tree root
".listings[0]" + // get listings array's first (only) object
".categories[0]" + // get categories array's first (only) object
".id"; // get id property
String lastParentIdJsonPath =
"$" + // start from tree root
".listings[0]" + // get listings array's first (only) object
".categories[0]" + // get categories array's first (only) object
"..parentCategory" + // do deep scan for all nested parentCategory objects
"[?(!(@.parentCategory))]" + // filter by the object that does NOT have parentCategory property
".id"; // get id property
try {
// read the whole input so it can be scanned twice
String jsonInput = new String(Files.readAllBytes(Paths.get("C://temp/test.json")), Charset.forName("UTF-8"));
String categoryId = JsonPath.read(jsonInput, categoryIdJsonPath);
System.out.println(categoryId);
// return type is always List when deep scan is requested
List<String> lastParent = JsonPath.read(jsonInput, lastParentIdJsonPath);
System.out.println(lastParent.get(0));
} catch (Exception e) {
e.printStackTrace();
}