繁体   English   中英

如何使用 spring 引导 api 调用提取嵌套的 json 值

[英]How to extract nested json values by using spring boot api call

我有以下 json。

[
    {
        "id": 1,
        "footwearList": [
            {
                "id": 1,
                "name": "sandals",
                "category": "men"
            },
            {
                "id": 3,
                "name": "sandals",
                "category": "women"
            }
        ],
        "clothingList": [
            {
                "id": 1,
                "name": "t-shirt",
                "category": "men"
            },
            {
                "id": 3,
                "name": "tshirt",
                "category": "women"
            }
        ]
    },
    {
        "id": 2,
        "footwearList": [
            {
                "id": 2,
                "name": "shoes",
                "category": "men"
            },
            {
                "id": 4,
                "name": "shoes",
                "category": "women"
            }
        ],
        "clothingList": [
            {
                "id": 2,
                "name": "shirt",
                "category": "men"
            },
            {
                "id": 4,
                "name": "shirt",
                "category": "women"
            }
        ]
    }
]

从 controller 的 api 调用中获取此 json,并希望从 json 到 881290284135988 从 controller 调用中获取嵌套值,例如(footwearlist,clothinglist)。如果找到,则通过过滤类别再次获取。

我尝试在 pom.xml 中使用添加了依赖项的 JsonPath

依赖:

<dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path</artifactId>
            <version>2.7.0</version>
        </dependency>

试图获取嵌套的 json 但没有成功。

    public List<Store> getCategory(){
        List<Store> footwear = JsonPath.read(json, "$..footwear");
    }

不需要引入新的依赖,有几种可能的方法可以使用 Jackson 解决这个问题。

Jackson 流媒体 API

如果出于某种原因,您不想将所有数据具体化为对象并希望对其进行迭代。 然后使用ObjectMapper.readTree()从您的 JSON 生成一个JsonNode ,并检查每个嵌套节点的字段名称。 为此,您可以使用JsonNode.fields() 如果遇到匹配字段 - 获取数据。

要检查字段是否匹配,您可以使用正则表达式。 这是基于正则表达式的谓词,它会检查给定的字符串是否包含 substring "footwear"

public static final Predicate<String> FOOTWEAR = Pattern.compile("footwear").asPredicate();

这就是迭代具有您显示的结构的树的代码可能如下所示:

String json = // incoming JSON
        
ObjectMapper mapper = new ObjectMapper();
        
List<Item> items = StreamSupport.stream(mapper.readTree(json).spliterator(), false)
    .<JsonNode>mapMulti((node, consumer) ->
        node.fields().forEachRemaining(entry -> {
            if (FOOTWEAR.test(entry.getKey())) entry.getValue().forEach(consumer);
        })
    )
    .map(StreamingNestedObjects::nodeToItem)
    .toList();
        
items.forEach(System.out::println);

Output:

Item{id=1, name='sandals', category='men'}
Item{id=3, name='sandals', category='women'}
Item{id=2, name='shoes', category='men'}
Item{id=4, name='shoes', category='women'}

假设Item class 如下所示:

public class Item {
    private int id;
    private String name;
    private String category;
    
    // getters, setters, etc.
}

但是传入的 JSON 不是很大,我建议使用 Jackson 的数据绑定。

数据绑定

考虑以下 class Store

public class Store {
    private int id;
    private Map<String, List<Item>> items = new HashMap<>();
    
    @JsonAnySetter
    public void readStore(String key, List<Item> value) {
        items.put(key, value);
    }

    @JsonAnyGetter
    public Map<String, List<Item>> writeStore(String key, List<Item> value) {
        return items;
    }

    // no-args constructor, getter and setter for id property, etc.
}

它的一个属性是 map 类型的Map<String, List<Item>>包含项目列表。 这个 map 可以通过@JsonAnySetter@JsonAnyGetter序列化/反序列化。

那就是如何将传入的 JSON 解析为Store实例列表:

ObjectMapper mapper = new ObjectMapper();
        
List<Store> stores = mapper.readValue(json, new TypeReference<>() {});

然后遍历列表,检查地图的并选择您需要的商店。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM