当前位置: 首页 > 面试题库 >

使用杰克逊解析递归嵌套字段

洪胤
2023-03-14
问题内容

我有一个下面的JSON,我需要从中制作一个Map<String, String>。在下面的JSON中,我只有3个级别,parentCategory但通常可以更高,有时也可以更低。

  • 我图的关键是79720idcategories部分和值应10987id最后parentCategory

现在我可以嵌套parentCategory在其中,因此在为此创建POJO时遇到问题。我可以有一个级别parentCategory,也可以嵌套parentCategory在每个级别中,parentCategory而我总是需要获取最后一个的ID
parentCategory

因此,我通过转到jsonschema2pojo来为此创建一个POJO,并提供了JSON,它在其中生成了我所需的所有文件。随着下面的JSON,它创造了三个班这样的ParentCategoryParentCategory_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();
    }


 类似资料:
  • 我想使用Spring的RestTemplate plus Jackson来使用Web服务。我已经学习了几本教程,并且已经达到了创建DAO的目的。这是我获取所有域对象的方法: 但我的Web服务不会立即返回Station对象数组,而是以这种方式返回一个更具语义的表达式: 所以我的问题是,我不知道如何“告诉”RestTemplate在“stations”指示符之后立即解析对象列表,而不创建临时对象,这似

  • 问题内容: 我正在尝试使用Jakson反序列化嵌套的多态类型。意思是我的顶级类型引用了另一个多态类型,该类型最终由不是抽象的类扩展。这不起作用,并引发异常。 这是我要尝试做的简化示例。 我得到有关抽象类型的标准例外。 让我解释一下我的用例。我有一个描述数据工作流程的Json文档。我在“一级”有一个抽象类型,描述了对单个值的操作。我派生了一堆不是抽象的类,它们实现了常见的操作(我用@JsonSubT

  • 问题内容: 我正在创建具有嵌套列表的API。杰克逊似乎是创建对象的好工具,但我还不太清楚如何嵌套列表,我想知道它是否可能。 我的对象看起来像这样。 我希望有一种将其映射到看起来像这样的json的方法: 我们希望能够做到这一点,因此我们可以将属性添加到列表中。 问题答案: 您可以为编写自定义解串器。请参见以下示例: 现在,您必须通知Jackson将其用于您的财产。您可以通过以下方式执行此操作:

  • 问题内容: 我有一个树对象结构,需要进行序列化,并且我希望每次能够使用jackson(或任何其他库-我打开)基于参数来控制序列化的深度。 我的课是这样的: 这是我想根据深度级别获得的2个序列化json的示例 深度级别设置为3 深度级别设置为2 有什么方法可以控制递归对象中序列化的深度? 谢谢 问题答案: 您需要实现自定义序列化程序,在其中需要计算已经处理的对象的数量。对于每个序列化过程,我们需要在

  • 问题内容: 在Jersey上使用Jackson 处理器时,何时以及为何需要在两者之间使用注释? 杰克逊(Jackson)还提供了自己的服务提供商以直接使用。这种方法缺少什么?还是为什么我比其他人更喜欢 ps:我也用弹簧 问题答案: 为了生成JSON,通常只需指定即可。但是,这将默认采用JAXB路由。 使用Object-> JAXB-> JSON,您必须注释要映射的类。这可以很好地工作,但是一旦您要

  • 我如何告诉Jackson忽略JSON名称? 我有以下POJO: 当我有这样的东西: “ABCName”:“foo”,然后杰克逊没有认出它抛出错误。 它期望的是: “abcName”:“foo”。 代码: 输出:{"abcname":"Foo"} 然后我试着用@JsonProperty(“ABCName”)注释ABCName 在我注释并运行代码之后,我得到的是:{“ABCName”:“Foo”,“A