I have a form that contains multiple radio inputs and one textarea input that I send using axios from a ReactJs client. The request looks like this:
axios.post("/wellbeing/" params.wellbeingSurveyType, { formAnswersJson: formAnswers })
.then(res => {
// logic
})
.catch(err => {
// logic
})
The 'formAnswers' object looks like this:
I then receive the request from a Spring controller that looks like the following:
@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
}
When I call the 'toString()' method on the result object it seems to correctly print out the map values:
But when I try to actually operate on the object (which is parsed as a LinkedHashMap) I cannot access the keys or values:
When I try to open up the object using the debugging tool it seems to store a reference to itself as a value:
The result I want is simply a Map<String, String> that represents the JSON but I am unsure why this behavior is happening.
Any help or tips on how to do this in a better way would be greatly appreciated, thank you.
CodePudding user response:
If you pass a JavaScript object as the 2nd parameter to the axios.post()
function, Axios will automatically serialize the object to JSON for you.
So, with this line of code :
axios.post("/wellbeing/" params.wellbeingSurveyType, { formAnswersJson: formAnswers })
You are basically sending object with key fromAnswersJson
and value fromAnswers
to your rest controller and Spring will deserilize it like a Map
with key fromAnswersJson
and value fromAnswers
To get what you want just send your request like this :
axios.post("/wellbeing/" params.wellbeingSurveyType, formAnswers )
CodePudding user response:
Alright the best way I found to make this work was to deconstruct the JSON object in the axios post request like so:
axios.post("/wellbeing/" params.wellbeingSurveyType, { ...formAnswers })
.then(res => {
// logic
})
.catch(err => {
// logic
})
Works better as if I just pass the formAnswers object it unnecessarily wraps the object i.e. A hashmap that contains a single key-value pair 'formAnswers'.
Although as The Frozen One mentioned, it would be better to define a dedicated form object and take it as a param in the spring controller.
CodePudding user response:
It Seems like the conversion from String to Map in java does not go smoothly from what I see in your printscreen.
Personally, I do not work like that when I handle requests. I create a dto object and give that in the controller as input. The fact that you have variables that the name is a number make that a bit more complicated since java cannot accept that as a valid variable name, but probably (did not test it) can be overcome by using @JsonProperty. So my solution would be the following
@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;
...
}
I added lombok getters and setters ofcourse you can add your own if you don't use lombok.
Then replace the input in your controller
@PostMapping("{wellbeingSurveyType}")
public WellbeingSurveySubmission submitSurvey(
@PathVariable WellbeingSurveyType wellbeingSurveyType,
@RequestBody MyRequestDto request) throws JsonProcessingException {
request.getUserComment()
return new WellbeingSurveySubmission(); //ignore this
}