Assume we have an endpoint that returns string array, like this (ContentType is application/json)

["a","a","a"]

and retrieve it's response as Flux<String>

webClient.get().uri().retrieve()
.bodyToFlux(String.class)
.subscribe(s -> println(s))

In my opinion, it should print "a" for three times, but only prints ["a","a","a"]. However, there is a workaround, we can replace String.class with String[].class, but the result returned in semantic isn't a Flux anymore, but a Mono. (The version of Spring Webflux is 5.2.3-RELEASE)

Comment From: bringyou

Looks like this method is the cause BodyExtractors.readWithMessageReaders

private static <T, S extends Publisher<T>> S readWithMessageReaders(
            ReactiveHttpInputMessage message, BodyExtractor.Context context, ResolvableType elementType,
            Function<HttpMessageReader<T>, S> readerFunction,
            Function<UnsupportedMediaTypeException, S> errorFunction,
            Supplier<S> emptySupplier) {

        if (VOID_TYPE.equals(elementType)) {
            return emptySupplier.get();
        }
        MediaType contentType = Optional.ofNullable(message.getHeaders().getContentType())
                .orElse(MediaType.APPLICATION_OCTET_STREAM);

        return context.messageReaders().stream()
                .filter(reader -> reader.canRead(elementType, contentType))
                .findFirst()
                .map(BodyExtractors::<T>cast)
                .map(readerFunction)
                .orElseGet(() -> {
                    List<MediaType> mediaTypes = context.messageReaders().stream()
                            .flatMap(reader -> reader.getReadableMediaTypes().stream())
                            .collect(Collectors.toList());
                    return errorFunction.apply(
                            new UnsupportedMediaTypeException(contentType, mediaTypes, elementType));
                });
    }

StringReader.canRead only test the elementType. Maybe we should choose reader by mimeType first, then use canRead or test both elementType and contentType?

Comment From: rstoyanchev

This is described here https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-codecs-jackson.

There is an ambiguity with String and "application/json". It could be a serialized JSON text or a JSON array. We treat it as the former for several reasons. One because you can resolve the ambiguity with a target of Mono<List<String>> whereas the other way around there would be no option. Two because it avoids other issues with SSE streams. Three because JSON Strings are less common and a slightly less longer syntax seems acceptable.

Comment From: borissedlak

Can you provide a full request on that? I tried to follow the reference on the spring web documentation but I ended up with

Mono<List<String>>response = webClient.put() .uri(**) .retrieve() .bodyToFlux(String.class) .collectList() .block();

and the result is still a single element though my json is of form ["a","b","c"]

Comment From: rstoyanchev

If you want a single string, reduce the list by concatenating:

webClient.get().uri("/path")
    .retrieve()
    .bodyToFlux(String.class)
    .collect(Collectors.joining())

**Comment From: jdeex**

> 
> 
> Can you provide a full request on that? I tried to follow the reference on the spring web documentation but I ended up with
> 
> `Mono<List<String>>response = webClient.put() .uri(**) .retrieve() .bodyToFlux(String.class) .collectList() .block();`
> 
> and the result is still a single element though my json is of form `["a","b","c"]`

This in fact returns one String with the complete array in it



> 
> 
> If you want a single string, reduce the list by concatenating:
> 
> ```java
> webClient.get().uri("/path")
>   .retrieve()
>   .bodyToFlux(String.class)
>   .collect(Collectors.joining())
> ```

We don't want a single String, we want the List of values

If you get a application/json reply like ["a","b","c"] and process it with .bodyToFlux(String.class) .collectList() .block() you should get a List<String> right?




**Comment From: bringyou**

The workaround I mentioned is something like
```java
webClient.get().uri().retrieve().bodyToFlux(String[].class);   // now we get a flux<String[]> which only has one item
webClient.get().uri().retrieve().bodyToMono(String[].class);  // or a mono<String[]>

then you can convert string[] to any type you like

Comment From: jdeex

Thx for the workaround, I did something similar... I starting to think that this only happens with the String class, other pojos work as expected...

Comment From: pablo53

Having read the maintainers' response, I still can't understand why is this ticket closed, and why the following: ["a","b","c"] is interpreted by WebClient as a single string. Former RestTemplate interpreted it correctly as a collection. So, Flux should correctly parse it as a Flux<String> with 3 string elements, and not one string representing JSON. WebClient would be right, if the content was like this: "[\"a\",\"b\",\"c\"]". Then I'd agree that Flux should return one string element ["a","b","c"].