Search code examples
javajsonspring-bootamadeus

How do I parse a JSON request into a FlightOfferSearch[] object?


I have trouble deserializing the Response Example JSON for a FlightOfferSearch from here when passing it to my test REST controller:

@RestController
public class MyController {

  @PostMapping("/search")
  String searchHandler(@RequestBody FlightOfferSearch[] flightOfferSearches) {
    return flightOfferSearches[0].toString();
  }
}

(minimal example with just Spring Boot Starter App with "Web" dependency and gson 2.8.5 and amadeus-java 4.1.0 added in the pom.xml)

I'm getting this in IntelliJ:

2020-04-20 17:05:59.392  WARN 47240 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Conflicting setter definitions for property "fixedLengthStreamingMode": java.net.HttpURLConnection#setFixedLengthStreamingMode(1 params) vs java.net.HttpURLConnection#setFixedLengthStreamingMode(1 params); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Conflicting setter definitions for property "fixedLengthStreamingMode": java.net.HttpURLConnection#setFixedLengthStreamingMode(1 params) vs java.net.HttpURLConnection#setFixedLengthStreamingMode(1 params)
 at [Source: (PushbackInputStream); line: 1, column: 1]]

Process finished with exit code -1

and this in Postman:

"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Conflicting setter definitions for property \"fixedLengthStreamingMode\": java.net.HttpURLConnection#setFixedLengthStreamingMode(1 params) vs java.net.HttpURLConnection#setFixedLengthStreamingMode(1 params); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Conflicting setter definitions for property \"fixedLengthStreamingMode\": java.net.HttpURLConnection#setFixedLengthStreamingMode(1 params) vs java.net.HttpURLConnection#setFixedLengthStreamingMode(1 params)\n at [Source: (PushbackInputStream); line: 1, column: 1]"

All comments are appreciated, thanks!


Solution

  • You probably didn't create setters for some of the fields for your parameter class, but the problem lies deeper - your way of handling this, is incorrect. Spring's @RestController converts incoming payload from JSON to the object parameter of the controller method by default and converts return object to JSON.

    You don't need to include any extra dependencies apart spring-boot-starter-web, which includes a default Jackson JSON mapper.

    But even if you do use gson instead, Spring still will work this exact way only it'll use gson instead.

    Everything you need to do is to create a class, which represents your incoming json correctly and use that class as a parameter, it has to have an empty constructor, setters if you use this object as a request body and getters if you use that object as a response body.

    UPD: If you don't own the object you are using as a controller method's parameter - I recommend creating custom POJO anyway, using non-incapsulated third-party library considered a smell at least, it violates the encapsulation and creates tight coupling to the third-party library.