-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Add a Jackson 3 converter #4552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
sschuberth
wants to merge
2
commits into
lysine-dev:trunk
Choose a base branch
from
sschuberth:jackson3-converter
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| Jackson Converter | ||
| ================= | ||
|
|
||
| A `Converter` which uses [Jackson][1] 3 for serialization to and from JSON. | ||
|
|
||
| A default `ObjectMapper` instance will be created or one can be configured and passed to the | ||
| `JacksonConverterFactory` construction to further control the serialization. | ||
|
|
||
|
|
||
| Download | ||
| -------- | ||
|
|
||
| Download [the latest JAR][2] or grab via [Maven][3]: | ||
| ```xml | ||
| <dependency> | ||
| <groupId>com.squareup.retrofit2</groupId> | ||
| <artifactId>converter-jackson3</artifactId> | ||
| <version>latest.version</version> | ||
| </dependency> | ||
| ``` | ||
| or [Gradle][3]: | ||
| ```groovy | ||
| implementation 'com.squareup.retrofit2:converter-jackson3:latest.version' | ||
| ``` | ||
|
|
||
| Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. | ||
|
|
||
|
|
||
|
|
||
| [1]: https://github.com/FasterXML/jackson | ||
| [2]: https://search.maven.org/remote_content?g=com.squareup.retrofit2&a=converter-jackson3&v=LATEST | ||
| [3]: http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.squareup.retrofit2%22%20a%3A%22converter-jackson3%22 | ||
| [snap]: https://s01.oss.sonatype.org/content/repositories/snapshots/ | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| apply plugin: 'java-library' | ||
| apply plugin: 'com.vanniktech.maven.publish' | ||
|
|
||
| dependencies { | ||
| api projects.retrofit | ||
| api libs.jackson3Databind | ||
| compileOnly libs.findBugsAnnotations | ||
|
|
||
| testImplementation libs.junit | ||
| testImplementation libs.truth | ||
| testImplementation libs.okhttp.mockwebserver | ||
| testImplementation libs.testParameterInjector | ||
| testImplementation libs.jacksonAnnotations | ||
| testImplementation libs.jackson3DataformatCbor | ||
| } | ||
|
|
||
| jar { | ||
| manifest { | ||
| attributes 'Automatic-Module-Name': 'retrofit2.converter.jackson3' | ||
| } | ||
| } | ||
|
|
||
| java { | ||
| toolchain { | ||
| languageVersion = JavaLanguageVersion.of(17) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| POM_ARTIFACT_ID=converter-jackson3 | ||
| POM_NAME=Converter: Jackson3 | ||
| POM_DESCRIPTION=A Retrofit Converter which uses Jackson 3 for serialization. |
99 changes: 99 additions & 0 deletions
99
...nverters/jackson3/src/main/java/retrofit2/converter/jackson3/JacksonConverterFactory.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| /* | ||
| * Copyright (C) 2015 Square, Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package retrofit2.converter.jackson3; | ||
|
|
||
| import java.lang.annotation.Annotation; | ||
| import java.lang.reflect.Type; | ||
| import okhttp3.MediaType; | ||
| import okhttp3.RequestBody; | ||
| import okhttp3.ResponseBody; | ||
| import retrofit2.Call; | ||
| import retrofit2.Converter; | ||
| import retrofit2.Retrofit; | ||
| import tools.jackson.databind.JavaType; | ||
| import tools.jackson.databind.ObjectMapper; | ||
| import tools.jackson.databind.ObjectReader; | ||
| import tools.jackson.databind.ObjectWriter; | ||
|
|
||
| /** | ||
| * A {@linkplain Converter.Factory converter} which uses Jackson. | ||
| * | ||
| * <p>Because Jackson is so flexible in the types it supports, this converter assumes that it can | ||
| * handle all types. If you are mixing JSON serialization with something else (such as protocol | ||
| * buffers), you must {@linkplain Retrofit.Builder#addConverterFactory(Converter.Factory) add this | ||
| * instance} last to allow the other converters a chance to see their types. | ||
| */ | ||
| public final class JacksonConverterFactory extends Converter.Factory { | ||
| private static final MediaType DEFAULT_MEDIA_TYPE = | ||
| MediaType.get("application/json; charset=UTF-8"); | ||
|
|
||
| /** Create an instance using a default {@link ObjectMapper} instance for conversion. */ | ||
| public static JacksonConverterFactory create() { | ||
| return new JacksonConverterFactory(new ObjectMapper(), DEFAULT_MEDIA_TYPE, false); | ||
| } | ||
|
|
||
| /** Create an instance using {@code mapper} for conversion. */ | ||
| public static JacksonConverterFactory create(ObjectMapper mapper) { | ||
| return create(mapper, DEFAULT_MEDIA_TYPE); | ||
| } | ||
|
|
||
| /** Create an instance using {@code mapper} and {@code mediaType} for conversion. */ | ||
| @SuppressWarnings("ConstantConditions") // Guarding public API nullability. | ||
| public static JacksonConverterFactory create(ObjectMapper mapper, MediaType mediaType) { | ||
| if (mapper == null) throw new NullPointerException("mapper == null"); | ||
| if (mediaType == null) throw new NullPointerException("mediaType == null"); | ||
| return new JacksonConverterFactory(mapper, mediaType, false); | ||
| } | ||
|
|
||
| private final ObjectMapper mapper; | ||
| private final MediaType mediaType; | ||
| private final boolean streaming; | ||
|
|
||
| private JacksonConverterFactory(ObjectMapper mapper, MediaType mediaType, boolean streaming) { | ||
| this.mapper = mapper; | ||
| this.mediaType = mediaType; | ||
| this.streaming = streaming; | ||
| } | ||
|
|
||
| /** | ||
| * Return a new factory which streams serialization of request messages to bytes on the HTTP thread | ||
| * This is either the calling thread for {@link Call#execute()}, or one of OkHttp's background | ||
| * threads for {@link Call#enqueue}. Response bytes are always converted to message instances on | ||
| * one of OkHttp's background threads. | ||
| */ | ||
| public JacksonConverterFactory withStreaming() { | ||
| return new JacksonConverterFactory(mapper, mediaType, true); | ||
| } | ||
|
|
||
| @Override | ||
| public Converter<ResponseBody, ?> responseBodyConverter( | ||
| Type type, Annotation[] annotations, Retrofit retrofit) { | ||
| JavaType javaType = mapper.getTypeFactory().constructType(type); | ||
| ObjectReader reader = mapper.readerFor(javaType); | ||
| return new JacksonResponseBodyConverter<>(reader); | ||
| } | ||
|
|
||
| @Override | ||
| public Converter<?, RequestBody> requestBodyConverter( | ||
| Type type, | ||
| Annotation[] parameterAnnotations, | ||
| Annotation[] methodAnnotations, | ||
| Retrofit retrofit) { | ||
| JavaType javaType = mapper.getTypeFactory().constructType(type); | ||
| ObjectWriter writer = mapper.writerFor(javaType); | ||
| return new JacksonRequestBodyConverter<>(writer, mediaType, streaming); | ||
| } | ||
| } |
50 changes: 50 additions & 0 deletions
50
...ters/jackson3/src/main/java/retrofit2/converter/jackson3/JacksonRequestBodyConverter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| /* | ||
| * Copyright (C) 2015 Square, Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package retrofit2.converter.jackson3; | ||
|
|
||
| import okhttp3.MediaType; | ||
| import okhttp3.RequestBody; | ||
| import retrofit2.Converter; | ||
| import tools.jackson.core.JacksonException; | ||
| import tools.jackson.databind.ObjectWriter; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| final class JacksonRequestBodyConverter<T> implements Converter<T, RequestBody> { | ||
| private final ObjectWriter adapter; | ||
| private final MediaType mediaType; | ||
| private final boolean streaming; | ||
|
|
||
| JacksonRequestBodyConverter(ObjectWriter adapter, MediaType mediaType, boolean streaming) { | ||
| this.adapter = adapter; | ||
| this.mediaType = mediaType; | ||
| this.streaming = streaming; | ||
| } | ||
|
|
||
| @Override | ||
| public RequestBody convert(T value) throws IOException { | ||
| if (streaming) { | ||
| return new JacksonStreamingRequestBody(adapter, value, mediaType); | ||
| } | ||
|
|
||
| try { | ||
| byte[] bytes = adapter.writeValueAsBytes(value); | ||
| return RequestBody.create(bytes, mediaType); | ||
| } catch (JacksonException e) { | ||
| throw new IOException(e); | ||
| } | ||
| } | ||
| } | ||
40 changes: 40 additions & 0 deletions
40
...ers/jackson3/src/main/java/retrofit2/converter/jackson3/JacksonResponseBodyConverter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /* | ||
| * Copyright (C) 2015 Square, Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package retrofit2.converter.jackson3; | ||
|
|
||
| import okhttp3.ResponseBody; | ||
| import retrofit2.Converter; | ||
| import tools.jackson.core.JacksonException; | ||
| import tools.jackson.databind.ObjectReader; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| final class JacksonResponseBodyConverter<T> implements Converter<ResponseBody, T> { | ||
| private final ObjectReader adapter; | ||
|
|
||
| JacksonResponseBodyConverter(ObjectReader adapter) { | ||
| this.adapter = adapter; | ||
| } | ||
|
|
||
| @Override | ||
| public T convert(ResponseBody value) throws IOException { | ||
| try (value) { | ||
| return adapter.readValue(value.byteStream()); | ||
| } catch (JacksonException e) { | ||
| throw new IOException(e); | ||
| } | ||
| } | ||
| } |
50 changes: 50 additions & 0 deletions
50
...ters/jackson3/src/main/java/retrofit2/converter/jackson3/JacksonStreamingRequestBody.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| /* | ||
| * Copyright (C) 2025 Square, Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package retrofit2.converter.jackson3; | ||
|
|
||
| import okhttp3.MediaType; | ||
| import okhttp3.RequestBody; | ||
| import okio.BufferedSink; | ||
| import tools.jackson.core.JacksonException; | ||
| import tools.jackson.databind.ObjectWriter; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| final class JacksonStreamingRequestBody extends RequestBody { | ||
| private final ObjectWriter adapter; | ||
| private final Object value; | ||
| private final MediaType mediaType; | ||
|
|
||
| public JacksonStreamingRequestBody(ObjectWriter adapter, Object value, MediaType mediaType) { | ||
| this.adapter = adapter; | ||
| this.value = value; | ||
| this.mediaType = mediaType; | ||
| } | ||
|
|
||
| @Override | ||
| public MediaType contentType() { | ||
| return mediaType; | ||
| } | ||
|
|
||
| @Override | ||
| public void writeTo(BufferedSink sink) throws IOException { | ||
| try { | ||
| adapter.writeValue(sink.outputStream(), value); | ||
| } catch (JacksonException e) { | ||
| throw new IOException(e); | ||
| } | ||
| } | ||
| } |
2 changes: 2 additions & 0 deletions
2
retrofit-converters/jackson3/src/main/java/retrofit2/converter/jackson3/package-info.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| @retrofit2.internal.EverythingIsNonNull | ||
| package retrofit2.converter.jackson3; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion we can use a
Bufferhere?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean like
Why, what's the advantage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean
okio.Bufferwhich reuses internalbyte[]There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I could do
but I still don't see the benefit, esp. as I believe
ByteString.of()copies the data underneath.If you have a different proposal, please share the exact code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a dev env of this repo so I can only provide following pseudo code.
Like this: https://github.com/square/retrofit/blob/8e83a242eac1afc22a13c52098eddb27421353ff/retrofit-converters/gson/src/main/java/retrofit2/converter/gson/GsonRequestBodyConverter.java#L51-L53
But don't call
readByteStringat the end of it.Use this (copied from my code):
Well, if you want it to be simple you can ignore my comment.