如何使用spring Boot api调用提取嵌套json值

kjthegm6  于 2022-11-26  发布在  Spring
关注(0)|答案(1)|浏览(176)

我有下面的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"
            }
        ]
    }
]

已从控制器的API调用中提取此json,并希望通过控制器的API调用从json中提取嵌套值,如(foowearlist,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");
    }
sdnqo3pr

sdnqo3pr1#

没有必要引入新的依赖项,使用Jackson有几种可能的方法来解决这个问题。

Jackson流媒体API

如果出于某种原因,您不想将所有数据物化为对象,而是想对其进行迭代,那么可以使用ObjectMapper.readTree()从JSON生成一个JsonNode,并检查每个嵌套节点的字段名。为此,您可以使用JsonNode.fields()。如果遇到匹配的字段,则获取数据。
要检查字段是否匹配,可以使用正则表达式。下面是一个基于正则表达式的 predicate ,它将检查给定的字符串是否包含子字符串"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);
  • 输出:*
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类看起来像这样:

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

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

数据绑定

考虑以下类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<String, List<Item>>类型的Map。此Map可以通过@JsonAnySetter@JsonAnyGetter进行序列化/反序列化。
这就是如何将传入的JSON解析为Store示例的列表:

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

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

相关问题