0

While decoding Flux JSON to Java object, I am getting below exception:

2019-02-25 13:44:39.136 TRACE [{}] 25292 --- [reactor-http-nio-4] o.s.w.r.f.c.ExchangeFunctions            : [762021a9] Response 200 OK, headers={masked}
2019-02-25 13:44:39.195 ERROR [{}] 25292 --- [reactor-http-nio-4] r.M.C.2                                  : | onError(org.springframework.core.codec.DecodingException: JSON decoding error: Unexpected character ('[' (code 91)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('[' (code 91)): was expecting double-quote to start field name
 at [Source: UNKNOWN; line: 2, column: 3])
2019-02-25 13:44:39.196 ERROR [{}] 25292 --- [reactor-http-nio-4] r.M.C.2                                  : 
org.springframework.core.codec.DecodingException: JSON decoding error: Unexpected character ('[' (code 91)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('[' (code 91)): was expecting double-quote to start field name
 at [Source: UNKNOWN; line: 2, column: 3]
    at org.springframework.http.codec.json.Jackson2Tokenizer.tokenize(Jackson2Tokenizer.java:104) ~[spring-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]

Setting the mapper codec property as follows does not resolve the issue:

mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

Here dow the JSON response:

[
  {
    "id": "111",
    "description": "xyz"
  },
  {
    "id": "222",
    "description": "pqr"
  }
]

Here down the WebClient implementation:

public Mono<List<ItemServiceResponse>> getItems(ItemServiceRequest itemServiceRequest) {
return webClient
        .post()
        .contentType(MediaType.APPLICATION_JSON)
        .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_STREAM_JSON.toString())
        .body(Mono.just(itemServiceRequest), ItemServiceRequest.class)
        .retrieve()
        .bodyToFlux(ItemServiceResponse.class)
        .collectList()
        .log();
}

Here is the Java Object:

@Builder 
@Data 
@AllArgsConstructor 
@NoArgsConstructor 
public class ItemServiceResponse { 
  private String id; 
  private String description; 
}
Brian Clozel
  • 56,583
  • 15
  • 167
  • 176
Ravi Mishra
  • 329
  • 3
  • 6

2 Answers2

1

A terrible problem!!! I wasted my 4-5 days figuring out what is wrong in my code and tried all permutation combination but nothing worked.

But guys, Postman was the culprit, yeah that's right.

The actual response structure of the JSON I was getting:

{
  [
    {
      "id": "111",
      "description": "xyz"
    },
    {
      "id": "222",
      "description": "pqr"
    }
  ]
}

And that is malformed JSON. But Postman was autocorrecting somehow and was giving a correct response as JSON mentioned in the question and I was not looking more on the response because the status code was coming as 200 success.

Fortunately, I triggered Curl command and got the root cause. Please don't believe postman... it is damn smart to correct things which are not required.

Ravi Mishra
  • 329
  • 3
  • 6
0

The ObjectMapper is expecting a single object to be mapped from your Json repsonse as a ItemServiceResponse hence the exception (the mapper is expecting a quote).

You should update your WebClient invocation to map an array of ItemServiceResponse:

public Mono<List<ItemServiceResponse>> getItems(ItemServiceRequest itemServiceRequest) {
    return webClient
            .post()
            .contentType(MediaType.APPLICATION_JSON)
            .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_STREAM_JSON.toString())
            .body(Mono.just(itemServiceRequest), ItemServiceRequest.class)
            .retrieve()
            .bodyToFlux(ItemServiceResponse[].class) // <-- array of ItemServiceResponse
            .collectList()
            .log();
}
tmarwen
  • 15,750
  • 5
  • 43
  • 62