diff --git a/core/src/main/java/feign/Response.java b/core/src/main/java/feign/Response.java index 175a78a2c5..4479b18488 100644 --- a/core/src/main/java/feign/Response.java +++ b/core/src/main/java/feign/Response.java @@ -175,6 +175,25 @@ public Request request() { return request; } + public Charset charset() { + + Collection contentTypeHeaders = headers().get("Content-Type"); + + if (contentTypeHeaders != null) { + for (String contentTypeHeader : contentTypeHeaders) { + String[] contentTypeParmeters = contentTypeHeader.split(";"); + if (contentTypeParmeters.length > 1) { + String[] charsetParts = contentTypeParmeters[1].split("="); + if (charsetParts.length == 2 && "charset".equalsIgnoreCase(charsetParts[0].trim())) { + return Charset.forName(charsetParts[1]); + } + } + } + } + + return Util.UTF_8; + } + @Override public String toString() { StringBuilder builder = new StringBuilder("HTTP/1.1 ").append(status); diff --git a/jackson/src/main/java/feign/jackson/JacksonDecoder.java b/jackson/src/main/java/feign/jackson/JacksonDecoder.java index f4fa985753..d6c6bd84e7 100644 --- a/jackson/src/main/java/feign/jackson/JacksonDecoder.java +++ b/jackson/src/main/java/feign/jackson/JacksonDecoder.java @@ -13,15 +13,17 @@ */ package feign.jackson; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.Module; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.RuntimeJsonMappingException; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.lang.reflect.Type; +import java.nio.charset.Charset; +import java.util.Collection; import java.util.Collections; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.RuntimeJsonMappingException; import feign.Response; import feign.Util; import feign.codec.Decoder; @@ -47,7 +49,7 @@ public JacksonDecoder(ObjectMapper mapper) { public Object decode(Response response, Type type) throws IOException { if (response.body() == null) return null; - Reader reader = response.body().asReader(Util.UTF_8); + Reader reader = response.body().asReader(response.charset()); if (!reader.markSupported()) { reader = new BufferedReader(reader, 1); } @@ -66,4 +68,5 @@ public Object decode(Response response, Type type) throws IOException { throw e; } } + } diff --git a/jackson/src/test/java/feign/jackson/JacksonCodecTest.java b/jackson/src/test/java/feign/jackson/JacksonCodecTest.java index 2b0d4bfdd6..2b8bffcdd3 100644 --- a/jackson/src/test/java/feign/jackson/JacksonCodecTest.java +++ b/jackson/src/test/java/feign/jackson/JacksonCodecTest.java @@ -28,9 +28,12 @@ import org.junit.Test; import java.io.Closeable; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; @@ -169,6 +172,29 @@ public void customEncoder() { + "} ]"); } + @Test + public void decoderCharset() throws IOException { + Zone zone = new Zone("denominator.io.", "ÁÉÍÓÚÀÈÌÒÙÄËÏÖÜÑ"); + + Map> headers = new HashMap>(); + headers.put("Content-Type", Arrays.asList("application/json;charset=ISO-8859-1")); + + Response response = Response.builder() + .status(200) + .reason("OK") + .request(Request.create(HttpMethod.GET, "/api", Collections.emptyMap(), null, Util.UTF_8)) + .headers(headers) + .body(new String("" // + + "{" + System.lineSeparator() + + " \"name\" : \"DENOMINATOR.IO.\"," + System.lineSeparator() + + " \"id\" : \"ÁÉÍÓÚÀÈÌÒÙÄËÏÖÜÑ\"" + System.lineSeparator() + + "}").getBytes(StandardCharsets.ISO_8859_1)) + .build(); + assertEquals(zone.get("id"), + ((Zone) new JacksonDecoder().decode(response, new TypeReference() {}.getType())) + .get("id")); + } + @Test public void decodesIterator() throws Exception { List zones = new LinkedList();