David Cobo
9 years ago
committed by
Adrian Cole
8 changed files with 186 additions and 2 deletions
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
Jackson-Jaxb Codec |
||||
=================== |
||||
|
||||
This module adds support for encoding and decoding JSON via JAXB. |
||||
|
||||
Add `JacksonJaxbJsonEncoder` and/or `JacksonJaxbJsonDecoder` to your `Feign.Builder` like so: |
||||
|
||||
```java |
||||
GitHub github = Feign.builder() |
||||
.encoder(new JacksonJaxbJsonEncoder()) |
||||
.decoder(new JacksonJaxbJsonDecoder()) |
||||
.target(GitHub.class, "https://api.github.com"); |
||||
``` |
||||
|
||||
If you want to customize the `ObjectMapper` that is used, provide it to the `JacksonJaxbJsonEncoder` and `JacksonJaxbJsonDecoder`: |
||||
|
||||
```java |
||||
ObjectMapper mapper = new ObjectMapper() |
||||
.setSerializationInclusion(JsonInclude.Include.NON_NULL) |
||||
.configure(SerializationFeature.INDENT_OUTPUT, true) |
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
||||
|
||||
GitHub github = Feign.builder() |
||||
.encoder(new JacksonJaxbJsonEncoder(mapper)) |
||||
.decoder(new JacksonJaxbJsonDecoder(mapper)) |
||||
.target(GitHub.class, "https://api.github.com"); |
||||
``` |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
apply plugin: 'java' |
||||
|
||||
sourceCompatibility = 1.6 |
||||
|
||||
dependencies { |
||||
compile project(':feign-core') |
||||
compile 'javax.ws.rs:jsr311-api:1.1.1' |
||||
compile 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.6.1' |
||||
testRuntime 'com.sun.jersey:jersey-client:1.19' // for RuntimeDelegateImpl |
||||
testCompile 'junit:junit:4.12' |
||||
testCompile 'org.assertj:assertj-core:1.7.1' // last version supporting JDK 7 |
||||
testCompile project(':feign-core').sourceSets.test.output // for assertions |
||||
} |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
package feign.jackson.jaxb; |
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; |
||||
|
||||
import java.io.IOException; |
||||
import java.lang.reflect.Type; |
||||
|
||||
import feign.FeignException; |
||||
import feign.Response; |
||||
import feign.codec.Decoder; |
||||
|
||||
import static com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS; |
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE; |
||||
|
||||
public final class JacksonJaxbJsonDecoder implements Decoder { |
||||
private final JacksonJaxbJsonProvider jacksonJaxbJsonProvider; |
||||
|
||||
public JacksonJaxbJsonDecoder() { |
||||
this.jacksonJaxbJsonProvider = new JacksonJaxbJsonProvider(); |
||||
} |
||||
|
||||
public JacksonJaxbJsonDecoder(ObjectMapper objectMapper) { |
||||
this.jacksonJaxbJsonProvider = new JacksonJaxbJsonProvider(objectMapper, DEFAULT_ANNOTATIONS); |
||||
} |
||||
|
||||
@Override |
||||
public Object decode(Response response, Type type) throws IOException, FeignException { |
||||
return jacksonJaxbJsonProvider.readFrom(Object.class, type, null, APPLICATION_JSON_TYPE, null, response.body().asInputStream()); |
||||
} |
||||
} |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
package feign.jackson.jaxb; |
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.lang.reflect.Type; |
||||
import java.nio.charset.Charset; |
||||
|
||||
import feign.RequestTemplate; |
||||
import feign.codec.EncodeException; |
||||
import feign.codec.Encoder; |
||||
|
||||
import static com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS; |
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE; |
||||
|
||||
public final class JacksonJaxbJsonEncoder implements Encoder { |
||||
private final JacksonJaxbJsonProvider jacksonJaxbJsonProvider; |
||||
|
||||
public JacksonJaxbJsonEncoder() { |
||||
this.jacksonJaxbJsonProvider = new JacksonJaxbJsonProvider(); |
||||
} |
||||
|
||||
public JacksonJaxbJsonEncoder(ObjectMapper objectMapper) { |
||||
this.jacksonJaxbJsonProvider = new JacksonJaxbJsonProvider(objectMapper, DEFAULT_ANNOTATIONS); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException { |
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
||||
try { |
||||
jacksonJaxbJsonProvider.writeTo(object, bodyType.getClass(), null, null, APPLICATION_JSON_TYPE, null, outputStream); |
||||
template.body(outputStream.toByteArray(), Charset.defaultCharset()); |
||||
} catch (IOException e) { |
||||
throw new EncodeException(e.getMessage(), e); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
package feign.jackson.jaxb; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType; |
||||
import javax.xml.bind.annotation.XmlAccessorType; |
||||
import javax.xml.bind.annotation.XmlElement; |
||||
import javax.xml.bind.annotation.XmlRootElement; |
||||
|
||||
import feign.RequestTemplate; |
||||
import feign.Response; |
||||
|
||||
import static feign.Util.UTF_8; |
||||
import static feign.assertj.FeignAssertions.assertThat; |
||||
|
||||
public class JacksonJaxbCodecTest { |
||||
|
||||
@Test |
||||
public void encodeTest() { |
||||
JacksonJaxbJsonEncoder encoder = new JacksonJaxbJsonEncoder(); |
||||
RequestTemplate template = new RequestTemplate(); |
||||
|
||||
encoder.encode(new MockObject("Test"), MockObject.class, template); |
||||
|
||||
assertThat(template).hasBody("{\"value\":\"Test\"}"); |
||||
} |
||||
|
||||
@Test |
||||
public void decodeTest() throws Exception { |
||||
Response response = |
||||
Response.create(200, "OK", Collections.<String, Collection<String>>emptyMap(), "{\"value\":\"Test\"}", UTF_8); |
||||
JacksonJaxbJsonDecoder decoder = new JacksonJaxbJsonDecoder(); |
||||
|
||||
assertThat(decoder.decode(response, MockObject.class)) |
||||
.isEqualTo(new MockObject("Test")); |
||||
} |
||||
|
||||
@XmlRootElement |
||||
@XmlAccessorType(XmlAccessType.FIELD) |
||||
static class MockObject { |
||||
|
||||
@XmlElement |
||||
private String value; |
||||
|
||||
MockObject() { |
||||
} |
||||
|
||||
MockObject(String value) { |
||||
this.value = value; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (obj instanceof MockObject) { |
||||
MockObject other = (MockObject) obj; |
||||
return value.equals(other.value); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return value != null ? value.hashCode() : 0; |
||||
} |
||||
} |
||||
} |
@ -1,6 +1,7 @@
@@ -1,6 +1,7 @@
|
||||
rootProject.name='feign' |
||||
include 'core', 'sax', 'gson', 'httpclient', 'jackson', 'jaxb', 'jaxrs', 'okhttp', 'ribbon', 'slf4j' |
||||
include 'core', 'sax', 'gson', 'httpclient', 'jackson', 'jaxb', 'jaxrs', 'okhttp', 'ribbon', 'slf4j', 'jackson-jaxb' |
||||
|
||||
rootProject.children.each { childProject -> |
||||
childProject.name = 'feign-' + childProject.name |
||||
} |
||||
|
||||
|
Loading…
Reference in new issue