Skip to content

Commit 721a4e1

Browse files
authored
Add Moshi (#2182)
* Add Moshi * Update README.md --------- Co-authored-by: Vikramaditya Chhapwale <cvikramad@gmail.com>
1 parent 66f1fd4 commit 721a4e1

File tree

13 files changed

+707
-0
lines changed

13 files changed

+707
-0
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,17 @@ public class Example {
409409
For the lighter weight Jackson Jr, use `JacksonJrEncoder` and `JacksonJrDecoder` from
410410
the [Jackson Jr Module](./jackson-jr).
411411
412+
#### Moshi
413+
[Moshi](./moshi) includes an encoder and decoder you can use with a JSON API.
414+
Add `MoshiEncoder` and/or `MoshiDecoder` to your `Feign.Builder` like so:
415+
416+
```java
417+
GitHub github = Feign.builder()
418+
.encoder(new MoshiEncoder())
419+
.decoder(new MoshiDecoder())
420+
.target(GitHub.class, "https://api.github.com");
421+
```
422+
412423
#### Sax
413424
[SaxDecoder](./sax) allows you to decode XML in a way that is compatible with normal JVM and also Android environments.
414425

moshi/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Moshi Codec
2+
===================
3+
4+
This module adds support for encoding and decoding JSON via the Moshi library.
5+
6+
Add `MoshiEncoder` and/or `MoshiDecoder` to your `Feign.Builder` like so:
7+
8+
```java
9+
GitHub github = Feign.builder()
10+
.encoder(new MoshiEncoder())
11+
.decoder(new MoshiDecoder())
12+
.target(GitHub.class, "https://api.github.com");
13+
```

moshi/pom.xml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2012-2023 The Feign Authors
5+
6+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7+
in compliance with the License. You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software distributed under the License
12+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13+
or implied. See the License for the specific language governing permissions and limitations under
14+
the License.
15+
16+
-->
17+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
18+
<modelVersion>4.0.0</modelVersion>
19+
20+
<parent>
21+
<groupId>io.github.openfeign</groupId>
22+
<artifactId>parent</artifactId>
23+
<version>13.0-SNAPSHOT</version>
24+
</parent>
25+
26+
<artifactId>feign-moshi</artifactId>
27+
<name>Feign Moshi</name>
28+
<description>Feign Moshi</description>
29+
30+
<properties>
31+
<main.basedir>${project.basedir}/..</main.basedir>
32+
</properties>
33+
34+
<dependencies>
35+
<dependency>
36+
<groupId>${project.groupId}</groupId>
37+
<artifactId>feign-core</artifactId>
38+
</dependency>
39+
40+
<dependency>
41+
<groupId>com.squareup.moshi</groupId>
42+
<artifactId>moshi</artifactId>
43+
</dependency>
44+
45+
<dependency>
46+
<groupId>com.google.guava</groupId>
47+
<artifactId>guava</artifactId>
48+
<version>${guava.version}</version>
49+
</dependency>
50+
51+
<dependency>
52+
<groupId>${project.groupId}</groupId>
53+
<artifactId>feign-core</artifactId>
54+
<type>test-jar</type>
55+
<scope>test</scope>
56+
</dependency>
57+
</dependencies>
58+
</project>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2012-2023 The Feign Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
package feign.moshi;
15+
16+
import com.google.common.io.CharStreams;
17+
import com.squareup.moshi.JsonAdapter;
18+
import com.squareup.moshi.JsonDataException;
19+
import com.squareup.moshi.JsonEncodingException;
20+
import com.squareup.moshi.Moshi;
21+
import feign.Response;
22+
import feign.Util;
23+
import feign.codec.Decoder;
24+
import java.io.IOException;
25+
import java.io.Reader;
26+
import java.lang.reflect.Type;
27+
import static feign.Util.UTF_8;
28+
import static feign.Util.ensureClosed;
29+
30+
public class MoshiDecoder implements Decoder {
31+
private final Moshi moshi;
32+
33+
public MoshiDecoder(Moshi moshi) {
34+
this.moshi = moshi;
35+
}
36+
37+
public MoshiDecoder() {
38+
this.moshi = new Moshi.Builder().build();
39+
}
40+
41+
public MoshiDecoder(Iterable<JsonAdapter<?>> adapters) {
42+
this(MoshiFactory.create(adapters));
43+
}
44+
45+
46+
@Override
47+
public Object decode(Response response, Type type) throws IOException {
48+
JsonAdapter<Object> jsonAdapter = moshi.adapter(type);
49+
50+
if (response.status() == 404 || response.status() == 204)
51+
return Util.emptyValueOf(type);
52+
if (response.body() == null)
53+
return null;
54+
55+
Reader reader = response.body().asReader(UTF_8);
56+
57+
try {
58+
return parseJson(jsonAdapter, reader);
59+
} catch (JsonDataException e) {
60+
if (e.getCause() != null && e.getCause() instanceof IOException) {
61+
throw (IOException) e.getCause();
62+
}
63+
throw e;
64+
} finally {
65+
ensureClosed(reader);
66+
}
67+
}
68+
69+
private Object parseJson(JsonAdapter<Object> jsonAdapter, Reader reader) throws IOException {
70+
String targetString = CharStreams.toString(reader);
71+
return jsonAdapter.fromJson(targetString);
72+
}
73+
}
74+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2012-2023 The Feign Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
package feign.moshi;
15+
16+
import com.squareup.moshi.JsonAdapter;
17+
import com.squareup.moshi.Moshi;
18+
import feign.RequestTemplate;
19+
import feign.codec.Encoder;
20+
import java.lang.reflect.Type;
21+
import java.util.Collections;
22+
23+
public class MoshiEncoder implements Encoder {
24+
25+
private final Moshi moshi;
26+
27+
public MoshiEncoder() {
28+
this.moshi = new Moshi.Builder().build();
29+
}
30+
31+
public MoshiEncoder(Moshi moshi) {
32+
this.moshi = moshi;
33+
}
34+
35+
public MoshiEncoder(Iterable<JsonAdapter<?>> adapters) {
36+
this(MoshiFactory.create(adapters));
37+
}
38+
39+
@Override
40+
public void encode(Object object, Type bodyType, RequestTemplate template) {
41+
JsonAdapter<Object> jsonAdapter = moshi.adapter(bodyType).indent(" ");
42+
template.body(jsonAdapter.toJson(object));
43+
}
44+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2012-2023 The Feign Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
package feign.moshi;
15+
16+
import com.squareup.moshi.JsonAdapter;
17+
import com.squareup.moshi.Moshi;
18+
19+
public class MoshiFactory {
20+
private MoshiFactory() {}
21+
22+
/**
23+
* Registers JsonAdapter by implicit type. Adds one to read numbers in a {@code Map<String,
24+
* Object>} as Integers.
25+
*/
26+
static Moshi create(Iterable<JsonAdapter<?>> adapters) {
27+
Moshi.Builder builder = new Moshi.Builder();
28+
29+
for (JsonAdapter<?> adapter : adapters) {
30+
builder.add(adapter.getClass(), adapter);
31+
}
32+
33+
return builder.build();
34+
}
35+
}
36+

0 commit comments

Comments
 (0)