Spring 没有正确地将 JSON 序列化为 Java 映射

Spring doesn't correctly serialize JSON to Java Map

我有一个包含多个无线电输入和一个文本区域输入的表单,我使用来自 ReactJs 客户端的 axios 发送这些输入。请求如下所示:

  axios.post("/wellbeing/" + params.wellbeingSurveyType, { formAnswersJson: formAnswers })
    .then(res => {
      // logic
    })
    .catch(err => {
      // logic
    })

'formAnswers' 对象如下所示:

然后我收到来自 Spring 控制器的请求,如下所示:

    @PostMapping("{wellbeingSurveyType}")
    public WellbeingSurveySubmission submitSurvey(
            @PathVariable WellbeingSurveyType wellbeingSurveyType,
            @RequestBody String formAnswersJson) throws JsonProcessingException {
        var result = new ObjectMapper().readValue(formAnswersJson, HashMap.class);
        return new WellbeingSurveySubmission(); //ignore this
    }

当我在结果对象上调用 'toString()' 方法时,它似乎正确地打印出了地图值:

但是当我尝试对对象(被解析为 LinkedHashMap)进行实际操作时,我无法访问键或值:

当我尝试使用调试工具打开对象时,它似乎将对自身的引用存储为一个值:

我想要的结果只是一个代表 JSON 的 Map 但我不确定为什么会发生这种行为。

任何有关如何更好地执行此操作的帮助或提示,我们将不胜感激,谢谢。

如果你将一个JavaScript对象作为第二个参数传递给axios.post()函数,Axios会自动为你将该对象序列化为JSON。

因此,使用这行代码:

axios.post("/wellbeing/" + params.wellbeingSurveyType, { formAnswersJson: formAnswers })

您基本上是将带有键 fromAnswersJson 和值 fromAnswers 的对象发送到您的其余控制器,并且 Spring 将像带有键 [=13= 的 Map 一样反序列化它] 和值 fromAnswers

要得到你想要的,只需像这样发送你的请求:

axios.post("/wellbeing/" + params.wellbeingSurveyType, formAnswers )

好吧,我发现完成这项工作的最佳方法是解构 axios post 请求中的 JSON 对象,如下所示:

axios.post("/wellbeing/" + params.wellbeingSurveyType, { ...formAnswers })
        .then(res => {
          // logic
        })
        .catch(err => {
          // logic
        })

效果更好,就好像我只是传递 formAnswers 对象一样,它不必要地包装对象,即包含单个 key-value 对 'formAnswers'.

的哈希图

尽管如 The Frozen One 所述,最好定义一个专用的表单对象并将其作为 spring 控制器中的参数。

从我在您的打印屏幕上看到的情况来看,java 中从 String 到 Map 的转换似乎并不顺利。

就个人而言,我在处理请求时不会那样工作。我创建了一个 dto 对象并将其作为输入提供给控制器。事实上,你的变量名称是一个数字,这使得它变得有点复杂,因为 java 不能接受它作为一个有效的变量名称,但可能(没有测试它)可以通过使用 @JsonProperty 来克服。所以我的解决方案如下

@Getter
@Setter
public class MyRequestDto {
    @JsonProperty("user-comment")
    private String userComment;
    @JsonProperty("0")
    private String zero;
    @JsonProperty("1")
    private String one;
    @JsonProperty("2")
    private String two;
...

}

我添加了 lombok getters 和 setters 当然如果你不使用 lombok 你可以添加你自己的。

然后替换控制器中的输入

@PostMapping("{wellbeingSurveyType}")
public WellbeingSurveySubmission submitSurvey(
        @PathVariable WellbeingSurveyType wellbeingSurveyType,
        @RequestBody MyRequestDto request) throws JsonProcessingException {
        request.getUserComment()
        return new WellbeingSurveySubmission(); //ignore this
    }