使用jackson解析递归嵌套字段

时间:2018-01-24 23:20:43

标签: java json parsing jackson jackson2

我有一个JSON以下,我需要从中创建一个Map<String, String>。在下面的JSON中,我只有三个parentCategory级别,但一般来说它可以更多或有时可以更少。

  • 我的地图的密钥为79720id部分为categories,其值应为10987idparentCategory。 }。

现在我可以在其中嵌套parentCategory,因此我遇到了为此制作POJO的问题。我可以有一个级别parentCategory,或者我可以在每个parentCategory内嵌套parentCategory,我总是需要获取最后一个parentCategory的ID。

所以我为此创建了一个POJO,转到jsonschema2pojo并提供了我的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结构。

以下是基于上述JSON生成的ParentCategory的三个类,但一般情况下我可以有多个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>();

    ...

}

1 个答案:

答案 0 :(得分:1)

一般而言 - 检索特定JSON属性的最佳工具是Json-Path,它提供了丰富的查询语言来搜索JSON树。

关于这个问题,需要检索两个不相关的属性,因此需要对JSON树进行两次扫描。问题没有说明如何读取输入,所以也许可以将整个输入流读入一个字符串。

下面是包含检索这两个属性所需查询的代码。无论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();
    }