Skip to content

Commit cf30603

Browse files
committed
Support for JSON Binding API (JSON-B)
Issue: SPR-14923
1 parent e5fdd4c commit cf30603

File tree

6 files changed

+367
-2
lines changed

6 files changed

+367
-2
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ project("spring-web") {
735735
optional("com.fasterxml.jackson.dataformat:jackson-dataformat-smile:${jackson2Version}")
736736
optional("com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:${jackson2Version}")
737737
optional("com.google.code.gson:gson:${gsonVersion}")
738+
optional("javax.json.bind:javax.json.bind-api:1.0.0-M1")
738739
optional("com.rometools:rome:${romeVersion}")
739740
optional("org.eclipse.jetty:jetty-servlet:${jettyVersion}") {
740741
exclude group: "javax.servlet", module: "javax.servlet-api"
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright 2002-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.http.converter.json;
18+
19+
import java.io.Reader;
20+
import java.io.Writer;
21+
import java.lang.reflect.Type;
22+
import javax.json.bind.Jsonb;
23+
import javax.json.bind.JsonbBuilder;
24+
import javax.json.bind.JsonbConfig;
25+
26+
import org.springframework.util.Assert;
27+
28+
/**
29+
* Implementation of {@link org.springframework.http.converter.HttpMessageConverter}
30+
* that can read and write JSON using the
31+
* <a href="http://json-b.net/">JSON Binding API</a>.
32+
*
33+
* <p>This converter can be used to bind to typed beans or untyped {@code HashMap}s.
34+
* By default, it supports {@code application/json} and {@code application/*+json} with
35+
* {@code UTF-8} character set.
36+
*
37+
* @author Juergen Hoeller
38+
* @since 5.0
39+
* @see javax.json.bind.Jsonb
40+
* @see javax.json.bind.JsonbBuilder
41+
* @see #setJsonb
42+
*/
43+
public class JsonbHttpMessageConverter extends AbstractJsonHttpMessageConverter {
44+
45+
private Jsonb jsonb;
46+
47+
48+
/**
49+
* Construct a new {@code JsonbHttpMessageConverter} with default configuration.
50+
*/
51+
public JsonbHttpMessageConverter() {
52+
this(JsonbBuilder.create());
53+
}
54+
55+
/**
56+
* Construct a new {@code JsonbHttpMessageConverter} with the given configuration.
57+
* @param config the {@code JsonbConfig} for the underlying delegate
58+
*/
59+
public JsonbHttpMessageConverter(JsonbConfig config) {
60+
this(JsonbBuilder.create(config));
61+
}
62+
63+
/**
64+
* Construct a new {@code JsonbHttpMessageConverter} with the given delegate.
65+
* @param jsonb the Jsonb instance to use
66+
*/
67+
public JsonbHttpMessageConverter(Jsonb jsonb) {
68+
setJsonb(jsonb);
69+
}
70+
71+
72+
/**
73+
* Set the {@code Jsonb} instance to use.
74+
* If not set, a default {@code Jsonb} instance will be created.
75+
* <p>Setting a custom-configured {@code Jsonb} is one way to take further
76+
* control of the JSON serialization process.
77+
* @see #JsonbHttpMessageConverter(Jsonb)
78+
* @see #JsonbHttpMessageConverter(JsonbConfig)
79+
* @see JsonbBuilder
80+
*/
81+
public void setJsonb(Jsonb jsonb) {
82+
Assert.notNull(jsonb, "A Jsonb instance is required");
83+
this.jsonb = jsonb;
84+
}
85+
86+
/**
87+
* Return the configured {@code Jsonb} instance for this converter.
88+
*/
89+
public Jsonb getJsonb() {
90+
return this.jsonb;
91+
}
92+
93+
94+
@Override
95+
protected Object readInternal(Type resolvedType, Reader reader) throws Exception {
96+
return getJsonb().fromJson(reader, resolvedType);
97+
}
98+
99+
@Override
100+
protected void writeInternal(Object o, Type type, Writer writer) throws Exception {
101+
if (type != null) {
102+
getJsonb().toJson(o, type, writer);
103+
}
104+
else {
105+
getJsonb().toJson(o, writer);
106+
}
107+
}
108+
109+
}

spring-web/src/main/java/org/springframework/http/converter/support/AllEncompassingFormHttpMessageConverter.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import org.springframework.http.converter.FormHttpMessageConverter;
2020
import org.springframework.http.converter.json.GsonHttpMessageConverter;
21+
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
2122
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
2223
import org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter;
2324
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
@@ -51,6 +52,9 @@ public class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConv
5152
private static final boolean gsonPresent =
5253
ClassUtils.isPresent("com.google.gson.Gson", AllEncompassingFormHttpMessageConverter.class.getClassLoader());
5354

55+
private static final boolean jsonbPresent =
56+
ClassUtils.isPresent("javax.json.bind.Jsonb", AllEncompassingFormHttpMessageConverter.class.getClassLoader());
57+
5458

5559
public AllEncompassingFormHttpMessageConverter() {
5660
addPartConverter(new SourceHttpMessageConverter<>());
@@ -65,6 +69,9 @@ public AllEncompassingFormHttpMessageConverter() {
6569
else if (gsonPresent) {
6670
addPartConverter(new GsonHttpMessageConverter());
6771
}
72+
else if (jsonbPresent) {
73+
addPartConverter(new JsonbHttpMessageConverter());
74+
}
6875

6976
if (jackson2XmlPresent) {
7077
addPartConverter(new MappingJackson2XmlHttpMessageConverter());

spring-web/src/main/java/org/springframework/web/client/RestTemplate.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter;
4545
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
4646
import org.springframework.http.converter.json.GsonHttpMessageConverter;
47+
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
4748
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
4849
import org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter;
4950
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
@@ -143,6 +144,9 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
143144
private static final boolean gsonPresent =
144145
ClassUtils.isPresent("com.google.gson.Gson", RestTemplate.class.getClassLoader());
145146

147+
private static final boolean jsonbPresent =
148+
ClassUtils.isPresent("javax.json.bind.Jsonb", RestTemplate.class.getClassLoader());
149+
146150

147151
private final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
148152

@@ -182,6 +186,9 @@ else if (jaxb2Present) {
182186
else if (gsonPresent) {
183187
this.messageConverters.add(new GsonHttpMessageConverter());
184188
}
189+
else if (jsonbPresent) {
190+
this.messageConverters.add(new JsonbHttpMessageConverter());
191+
}
185192

186193
if (jackson2SmilePresent) {
187194
this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());

0 commit comments

Comments
 (0)