Describe the bug @SpringQueryMap doesn't support String[], but as @RequestParam String[] is working.

Sample Fiegn client interface with two different API methods

@FeignClient
public interface ApiClient {

    @GetMapping("/incorrect")
    ApiResponse<ResponseDto> findAll(@SpringQueryMap ApiParams params);

    @PostMapping("/correct")
    ApiResponse<ResponseDto> findMarkingCodes(@RequestParam String[] fields);

}

ApiParams class

@Data
@AllArgsConstructor
public class ApiParams {
    private String[] fields;
}

Expected Behaviour Expected url for request with @SpringQueryMap: https://url/incorrect?fields=name,surname Generated url for request with @SpringQueryMap: https://url/incorrect?fields=%5BLjava.lang.String%3B%405ed08faf&b=%5BLjava.lang.String%3B%4075386aa2

But when I'm trying to use String[], it works and generated url is as expected: https://url/correct?fields=name,surname

Comment From: MissingNone

You can implements the QueryMapEncoder interface.

public class FormQueryMapEncoder implements QueryMapEncoder {
    private MappingJackson2HttpMessageConverter converter;
    public FormQueryMapEncoder(MappingJackson2HttpMessageConverter converter) {
        this.converter = converter;
    }
    @Override
    public Map<String, Object> encode(Object object) {
        Map<String, Object> ret = converter.getObjectMapper().convertValue(object,HashMap.class);
        return ret;
    }
}

And then declare a QueryMapEncoder bean in JavaConfig.

@Bean
QueryMapEncoder queryMapEncoder() {
       return new FormQueryMapEncoder(mappingJackson2HttpMessageConverter);
 }

Comment From: OlgaMaciaszek

@rkovtiuk Does the provided workaround solve your issue?

Comment From: rkovtiuk

Hi @MissingNone, @OlgaMaciaszek,
No, it doesn't. I tried this example and see same: fields=%5BLjava.lang.String%3B%40e35dc14

I also tried this variant:

@Bean
public QueryMapEncoder queryMapEncoder(ObjectMapper objectMapper) {
   return object -> objectMapper.convertValue(object, new TypeReference<Map<String, Object>>() {});
}

But this also doesn't help.

Comment From: MissingNone

@rkovtiuk But I tried this is worked. Maybe Encoder is different with me.

config file:

@Configuration
public class CoreFeignConfiguration {
    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;
    @Autowired
    private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;

    @Bean
    @Primary
    @Scope(SCOPE_PROTOTYPE)
    Encoder feignFormEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }
    @Bean
    QueryMapEncoder queryMapEncoder() {
        return new FormQueryMapEncoder(mappingJackson2HttpMessageConverter);
    }

}

FormQueryMapEncoder.java

public class FormQueryMapEncoder implements QueryMapEncoder {
    private MappingJackson2HttpMessageConverter converter;
    public FormQueryMapEncoder(MappingJackson2HttpMessageConverter converter) {
        this.converter = converter;
    }
    @Override
    public Map<String, Object> encode(Object object) {
        Map<String, Object> ret = converter.getObjectMapper().convertValue(object,HashMap.class);
        return ret;
    }
}

version: spring-cloud-stater-openfeign:2.2.2.RELEASE

Can you provide a demo for your issue?

Comment From: rkovtiuk

My configuration

@Configuration
public class FeignConfiguration {

    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    public QueryMapEncoder queryMapEncoder(ObjectMapper objectMapper) {
        return object -> objectMapper.convertValue(object, new TypeReference<Map<String, Object>>() {});
    }

    @Bean
    @Primary
    @Scope(SCOPE_PROTOTYPE)
    public Encoder feignFormEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }

    @Bean
    public Client feignClient() {
        return new Client.Default(getSSLSocketFactory(), new NoopHostnameVerifier());
    }

    private SSLSocketFactory getSSLSocketFactory() {
        try {
            var sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
            return sslContext.getSocketFactory();
        } catch (Exception exception) {
            throw new RuntimeException(exception);
        }
    }

}

version: 2.1.2.RELEASE

Comment From: MissingNone

@rkovtiuk I used your version for project And find out it.

Beacause Feign still used default QueryMapEncoder instead of Our QueryMapEncoder bean before spring-cloud-stater-openfeign:2.0.0.M3.

So adding the Feign.Builder bean based on the previous then it worked on your version.

new configuration:

@Configuration
public class CoreFeignConfiguration {
    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    @Primary
    @Scope(SCOPE_PROTOTYPE)
    Encoder feignFormEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }
    @Bean
    QueryMapEncoder queryMapEncoder(ObjectMapper objectMapper) {
        return object-> objectMapper.convertValue(object, new TypeReference<Map<String, Object>>() {});
    }

    @Bean
    @Scope(SCOPE_PROTOTYPE)
    public Feign.Builder feignBuilder(QueryMapEncoder queryMapEncoder) {
        return Feign.builder().queryMapEncoder(queryMapEncoder);
    }

}

Comment From: rkovtiuk

@MissingNone, this configuration works for me thanks 😃

@Configuration
public class FeignConfiguration {

    @Bean
    public QueryMapEncoder queryMapEncoder(ObjectMapper objectMapper) {
        return object -> objectMapper.convertValue(object, new TypeReference<Map<String, Object>>() {});
    }

    @Bean
    @Scope(SCOPE_PROTOTYPE)
    public Feign.Builder feignBuilder(QueryMapEncoder queryMapEncoder) {
        return Feign.builder().queryMapEncoder(queryMapEncoder);
    }
}

But as I understood, this must work without this additional configuration.

Comment From: MissingNone

@rkovtiuk Yes,it's a bug. your issue is same as the issue #256.Issue https://github.com/OpenFeign/feign/issues/1170 mentioned it.

Comment From: OlgaMaciaszek

Closing in favour of OpenFeign/feign#1170.