簡體   English   中英

Spring 查詢轉換為嵌套的 JSON 結構

[英]Spring query convert to a nested JSON structure

I'm new to spring and Java and trying to figure out how to go about formatting the json response into the desired structure.

我有一個 spring 查詢,它從如下表中返回 2 列,這確實是 json 結構所需的鍵和值:

名稱 價值觀
豐田
自行車 施溫
小型摩托車 Razor
A0 11
A1 12
A2 13
B0 2000
B1 4000
B2 22000

來自 controller 的當前 json output 是這樣的:

[{
        "names": "Car",
        "values": "Toyota"
    },
    {
        "names": "Bike",
        "values": "Schwinn"
    },
    {
        "names": "Scooter",
        "values": "Razor"
    },
    {
        "names": "A0",
        "values": "11"
    },
    {
        "names": "A1",
        "values": "12"
    },
    {
        "names": "A2",
        "values": "13"
    },
    {
        "names": "B0",
        "values": "2000"
    },
    {
        "names": "B1",
        "values": "4000"
    },
    {
        "names": "B2",
        "values": "22000"
    }
]

所需的 json 格式是刪除表列名稱的地方,而是使用鍵的名稱列創建 json 結構:

{
    "Car": "Toyota",
    "Bike": "Schwinn",
    "Scooter": "Razor",
    "Data": [{
        "A0": "11",
        "B0": "2000"
    }, {
        "A1": "12",
        "B1": "4000"
    }, {
        "A2": "13",
        "B2": "22000"
    }]
}

存儲庫

   @Query (value = "Select names, values ... :id")
    List<Data> findData(@Param("id") Long id) ;

      interface Data {
        String getnames();
        String getvalues();
    }

服務

    public List<Data> getData(Long id) {return repo.findData(id);}

Controller

    @GetMapping("/getdata/{id}")
    public ResponseEntity<List<Data>> getData(@PathVariable Long id) {
            List<Data> c = service.getData(id);
            return new ResponseEntity<>(c, HttpStatus.OK);

    }

似乎我需要處理結果集並需要遍歷它們以創建所需的結構,但不確定如何繼續進行,或者可能有更簡單的方法來獲得所需的結構。 任何指導將不勝感激。

所以返回一個 ResponseEntity<Map<String, Object>> 而不是一個 List 來模擬一個 Json object。

List<Data> c = service.getData(id);

Map<String, Object> map = new HashMap<>();
map.put("Key", "Value");
map.put("Car", c.get(0).getvalues());
map.put("Entire List", c);

return new ResponseEntity<>(c, HttpStatus.OK);

顯然,您必須編寫自己的邏輯,但它應該非常簡單。 或者,更好的是,如果您要經常使用它,請考慮為返回的 object 制作一個 class,然后返回 ResponseEntity< YourCustomObject >

這看起來有點復雜,我認為您應該為 A0 B0 之類的值設置主鍵關聯


import com.black_dragon.utils.JacksonUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * @author black_dragon
 * @version V1.0
 * @Package com.black_dragon.swing
 * @date 2022/9/6 10:35
 * @Copyright
 */
public class ConvertToMap {
    String names;
    String values;

    public String getNames() {
        return names;
    }

    public void setNames(String names) {
        this.names = names;
    }


    public String getValues() {
        return values;
    }

    public void setValues(String values) {
        this.values = values;
    }

    private static String DIGIT_REGEX = "[^0-9]";

    private static String LETTER_DIGIT_REGEX = "[a-zA-Z]+";

    public static Integer getDigit(String str){
        Pattern pattern = Pattern.compile(DIGIT_REGEX);
        if(!isLetterDigit(str)){
            String[] keySet = pattern.split(str);
            if(keySet.length > 0){
                return Integer.valueOf(keySet[1]);
            }
        }
        return -1;
    }

    public static boolean isLetterDigit(String str){
        return str.matches(LETTER_DIGIT_REGEX);
    }

    private static String fetchGroupKey(ConvertToMap convertToMap){
        return String.valueOf(getDigit(convertToMap.names));
    }

    public static void main(String[] args) {
        String jsonString = "[{\n" +
                "        \"names\": \"Car\",\n" +
                "        \"values\": \"Toyota\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"names\": \"Bike\",\n" +
                "        \"values\": \"Schwinn\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"names\": \"Scooter\",\n" +
                "        \"values\": \"Razor\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"names\": \"A0\",\n" +
                "        \"values\": \"11\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"names\": \"A1\",\n" +
                "        \"values\": \"12\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"names\": \"A2\",\n" +
                "        \"values\": \"13\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"names\": \"B0\",\n" +
                "        \"values\": \"2000\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"names\": \"B1\",\n" +
                "        \"values\": \"4000\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"names\": \"B2\",\n" +
                "        \"values\": \"22000\"\n" +
                "    }\n" +
                "]";

        List<ConvertToMap> convertToMaps = JacksonUtils.toJavaList(jsonString, ConvertToMap.class);

        // Extract a string that does not contain numbers and convert it to a map
        Map<String, Object> result = convertToMaps.stream()
                .filter(x -> isLetterDigit(x.names))
                .collect(Collectors.toMap(ConvertToMap::getNames, ConvertToMap::getValues));
        List<Map<String, String>> mapList = new ArrayList<>();
        // Group by string numbers containing numbers
        Map<String, List<ConvertToMap>> stringListMap = convertToMaps.stream().collect(groupingBy(convertToMap -> fetchGroupKey(convertToMap)));
        for (String key : stringListMap.keySet()) {
            if(Integer.valueOf(key) >= 0){
                mapList.add(stringListMap.get(key)
                        .stream()
                        .collect(Collectors.toMap(ConvertToMap::getNames, ConvertToMap::getValues)));
            }
        }
        result.put("Data", mapList);
        System.out.println(JacksonUtils.toJSONString(result));
    }
}

假設您的數據密鑰名稱模式是一個非數字后跟數字。

https://github.com/octomix/josson

反序列化

Josson josson = Josson.fromJsonString(
    "[" +
    "    {" +
    "        \"names\": \"Car\"," +
    "        \"values\": \"Toyota\"" +
    "    }," +
    "    {" +
    "        \"names\": \"Bike\"," +
    "        \"values\": \"Schwinn\"" +
    "    }," +
    "    {" +
    "        \"names\": \"Scooter\"," +
    "        \"values\": \"Razor\"" +
    "    }," +
    "    {" +
    "        \"names\": \"A0\"," +
    "        \"values\": \"11\"" +
    "    }," +
    "    {" +
    "        \"names\": \"A1\"," +
    "        \"values\": \"12\"" +
    "    }," +
    "    {" +
    "        \"names\": \"A2\"," +
    "        \"values\": \"13\"" +
    "    }," +
    "    {" +
    "        \"names\": \"B0\"," +
    "        \"values\": \"2000\"" +
    "    }," +
    "    {" +
    "        \"names\": \"B1\"," +
    "        \"values\": \"4000\"" +
    "    }," +
    "    {" +
    "        \"names\": \"B2\"," +
    "        \"values\": \"22000\"" +
    "    }" +
    "]");
    

轉型

JsonNode node = josson.getNode(
    "toObject('o')" +
    ".collect(o[names !=~ '\\D\\d+']*" +
    "         .map(names::values)" +
    "        ,o[names =~ '\\D\\d+']*" +
    "         .group(names.substr(1), map(names::values))@" +
    "         .elements" +
    "         .mergeObjects()" +
    "         .@toObject('Data')" +
    ")" +
    ".flatten(1)" +
    ".mergeObjects()");
System.out.println(node.toPrettyString());

Output

{
  "Car" : "Toyota",
  "Bike" : "Schwinn",
  "Scooter" : "Razor",
  "Data" : [ {
    "A0" : "11",
    "B0" : "2000"
  }, {
    "A1" : "12",
    "B1" : "4000"
  }, {
    "A2" : "13",
    "B2" : "22000"
  } ]
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM