迭代 ResponseBody 中的项目并将它们放入 HashMap Spring Boot

Posted

技术标签:

【中文标题】迭代 ResponseBody 中的项目并将它们放入 HashMap Spring Boot【英文标题】:Iterate items in ResponseBody and put them in a HashMap Spring Boot 【发布时间】:2019-07-24 14:21:30 【问题描述】:

在 Spring Boot 的 REST 控制器中,我试图迭代 RequestBody 响应中的值,并将其中一些值放入 POST 端点的 HashMap 中。

我发送的 JSON 是这样的结构:

"name":"yogurt","vitaminA":6,"vitaminb12":5

到目前为止,端点看起来像这样:

@RequestMapping("/create")
public NutrientList createNUtrientList(@RequestBody NutrientList nutrientList) 
    Map<String, Double> nutrientMap = new HashMap<String,Double>();
    //get nutrient values, need help with this part
    for()
    //add values to map
    NutrientList nl = new NutrientList(nutrientList.getName(), nutrientMap);
    //will save to repository
    return nl;

NutrientList 类如下所示:

public class NutrientList 
    @Id
    private ObjectId id;
    @JsonProperty("name")
    private String name;
    @JsonProperty("nutrientMap")
    Map <String,Double> nutrientMap = new HashMap<String,Double>();

    public NutrientList() 

    public NutrientList(String name, Map<String, Double> nutrientMap) 
        this.id = new ObjectId();
        this.name = name;
        this.nutrientMap = nutrientMap;
    
    //setters and getters

数据以单独的营养素存储在数据库中,不是地图。我看到 NutrientList 类不共享相同的结构,但有什么办法可以解决这个问题,以便能够使用地图而不改变它在数据库中的存储方式?

我需要使用地图,因为有很多营养素,我不想为它们设置单独的变量。太感谢了。如果有不清楚的地方请告诉我。

编辑: 我可以交替地将我从数据库中获取数据的 csv 转换为带有地图的 JSON 格式,但我还没有找到一个在线工具可以给我这种灵活性。

【问题讨论】:

How do I efficiently iterate over each entry in a Java Map?的可能重复 感谢您的资源,但我不是想循环地图,而是将响应正文制作成地图。 您确定请求正文是 NutrientList 吗?好像和你展示的Json字符串不一样。 是的,它是不同的,但有什么办法可以解决这个问题? 我可以将参数更改为什么? 【参考方案1】:

如果您有有效密钥列表,则可以使用以下内容:

private static final List<String> validKeys = Arrays.asList("vitaminA", "vitaminB" /* ... */);

@RequestMapping("/create")
public NutrientList createNutrientList(@RequestBody Map<String, Object> requestBody) 
    Map<String, Double> nutrientMap = new HashMap<>();
    for (String nutrient : requestBody.keySet()) 
        if (validKeys.contains(nutrient) && requestBody.get(nutrient) instanceof Number) 
            Number number = (Number) requestBody.get(nutrient);
            nutrientMap.put(nutrient, number.doubleValue());
        
    
    String name = (String) requestBody.get("name"); // maybe check if name exists and is really a string
    return new NutrientList(name, nutrientMap);

如果你想使用 Java 8 Stream API 你可以试试:

private static final List<String> validKeys = Arrays.asList("vitaminA", "vitaminB" /* ... */);

@RequestMapping("/create")
public NutrientList createNutrientList(@RequestBody Map<String, Object> requestBody) 
    Map<String, Double> nutrientMap = requestBody.entrySet().stream()
            .filter(e -> validKeys.contains(e.getKey()))
            .filter(e -> e.getValue() instanceof Number)
            .collect(Collectors.toMap(Map.Entry::getKey, e -> ((Number) e.getValue()).doubleValue()));
    String name = Optional.ofNullable(requestBody.get("name"))
            .filter(n -> n instanceof String)
            .map(n -> (String) n)
            .orElseThrow(IllegalArgumentException::new);
    return new NutrientList(name, nutrientMap);

希望对您有所帮助。

【讨论】:

以上是关于迭代 ResponseBody 中的项目并将它们放入 HashMap Spring Boot的主要内容,如果未能解决你的问题,请参考以下文章

迭代 4 个 pandas 数据框列并将它们存储到 4 个列表中,其中一个 for 循环而不是 4 个 for 循环

spring 3.0 @ResponseBody注解返回中文问号乱码解决办法

Spring中的@RequestBody和@ResponseBody注解

如何迭代数据框中的行以检测不同的单词并将其保存在新列中?

我可以从这些单独的列表中迭代地分割我需要的位置并将它们放入另一个列表“系数”中,如下所示?

从 Firebase 集合中获取项目并将它们用作 Vue 中的列表