簡體   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