public abstract class Jackson
extends java.lang.Object
The methods that return a JsonRender
are to be used with the Context.render(Object)
method for serializing objects to the response as JSON.
import ratpack.test.embed.EmbeddedApp;
import ratpack.jackson.Jackson;
import ratpack.http.client.ReceivedResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import static ratpack.jackson.Jackson.json;
import static org.junit.Assert.*;
public class Example {
public static class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String... args) throws Exception {
EmbeddedApp.of(s -> s
.handlers(chain ->
chain.get(ctx -> ctx.render(json(new Person("John"))))
)
).test(httpClient -> {
ReceivedResponse response = httpClient.get();
assertEquals("{\"name\":\"John\"}", response.getBody().getText());
assertEquals("application/json", response.getBody().getContentType().getType());
});
}
}
There are several options for streaming JSON data and events.
The chunkedJsonList(Registry, Publisher)
method can be used for rendering a very large JSON stream/list without buffering the entire list in memory.
It is also easy to render server sent events
, which can be useful for real time applications and infinite data streams.
import ratpack.test.embed.EmbeddedApp;
import ratpack.jackson.Jackson;
import ratpack.stream.Streams;
import ratpack.http.client.ReceivedResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.reactivestreams.Publisher;
import java.util.Arrays;
import static ratpack.jackson.Jackson.toJson;
import static ratpack.sse.ServerSentEvents.serverSentEvents;
import static java.util.stream.Collectors.joining;
import static org.junit.Assert.*;
public class Example {
public static class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String... args) throws Exception {
EmbeddedApp.of(s -> s
.handlers(chain -> chain
.get("stream", ctx -> {
Publisher<Person> people = Streams.publish(Arrays.asList(
new Person("a"),
new Person("b"),
new Person("c")
));
ctx.render(serverSentEvents(people, e -> e.data(toJson(ctx))));
})
)
).test(httpClient -> {
ReceivedResponse response = httpClient.get("stream");
assertEquals("text/event-stream;charset=UTF-8", response.getHeaders().get("Content-Type"));
String expectedOutput = Arrays.asList("a", "b", "c")
.stream()
.map(i -> "data: {\"name\":\"" + i + "\"}\n")
.collect(joining("\n"))
+ "\n";
assertEquals(expectedOutput, response.getBody().getText());
});
}
}
A similar approach could be used directly with the Response.sendStream(Publisher)
method for a custom “protocol”.
The methods that return a Parse
are to be used with the Context.parse(ratpack.parse.Parse)
method for deserializing request bodies containing JSON.
import ratpack.test.embed.EmbeddedApp;
import ratpack.jackson.Jackson;
import ratpack.http.client.ReceivedResponse;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.reflect.TypeToken;
import java.util.List;
import static ratpack.util.Types.listOf;
import static ratpack.jackson.Jackson.jsonNode;
import static ratpack.jackson.Jackson.fromJson;
import static org.junit.Assert.*;
public class Example {
public static class Person {
private final String name;
public Person(@JsonProperty("name") String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String... args) throws Exception {
EmbeddedApp.of(s -> s
.handlers(chain -> chain
.post("asNode", ctx -> {
ctx.render(ctx.parse(jsonNode()).map(n -> n.get("name").asText()));
})
.post("asPerson", ctx -> {
ctx.render(ctx.parse(fromJson(Person.class)).map(p -> p.getName()));
})
.post("asPersonList", ctx -> {
ctx.render(ctx.parse(fromJson(listOf(Person.class))).map(p -> p.get(0).getName()));
})
)
).test(httpClient -> {
ReceivedResponse response = httpClient.requestSpec(s ->
s.body(b -> b.type("application/json").text("{\"name\":\"John\"}"))
).post("asNode");
assertEquals("John", response.getBody().getText());
response = httpClient.requestSpec(s ->
s.body(b -> b.type("application/json").text("{\"name\":\"John\"}"))
).post("asPerson");
assertEquals("John", response.getBody().getText());
response = httpClient.requestSpec(s ->
s.body(b -> b.type("application/json").text("[{\"name\":\"John\"}]"))
).post("asPersonList");
assertEquals("John", response.getBody().getText());
});
}
}
A NoOptParserSupport
parser is also rendered for the "application/json"
content type.
This allows the use of the Context.parse(java.lang.Class)
and Context.parse(com.google.common.reflect.TypeToken)
methods.
import ratpack.test.embed.EmbeddedApp;
import ratpack.jackson.Jackson;
import ratpack.http.client.ReceivedResponse;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.reflect.TypeToken;
import java.util.List;
import static ratpack.util.Types.listOf;
import static org.junit.Assert.*;
public class Example {
public static class Person {
private final String name;
public Person(@JsonProperty("name") String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String... args) throws Exception {
EmbeddedApp.of(s -> s
.handlers(chain -> chain
.post("asPerson", ctx -> {
ctx.parse(Person.class).then(person -> ctx.render(person.getName()));
})
.post("asPersonList", ctx -> {
ctx.parse(listOf(Person.class)).then(person -> ctx.render(person.get(0).getName()));
})
)
).test(httpClient -> {
ReceivedResponse response = httpClient.requestSpec(s ->
s.body(b -> b.type("application/json").text("{\"name\":\"John\"}"))
).post("asPerson");
assertEquals("John", response.getBody().getText());
response = httpClient.requestSpec(s ->
s.body(b -> b.type("application/json").text("[{\"name\":\"John\"}]"))
).post("asPersonList");
assertEquals("John", response.getBody().getText());
});
}
}
The Jackson API is based around the ObjectMapper
.
Ratpack adds a default instance to the base registry automatically.
To configure Jackson behaviour, override this instance.
import ratpack.test.embed.EmbeddedApp;
import ratpack.http.client.ReceivedResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import java.util.Optional;
import static ratpack.jackson.Jackson.json;
import static org.junit.Assert.*;
public class Example {
public static class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String... args) throws Exception {
EmbeddedApp.of(s -> s
.registryOf(r -> r
.add(new ObjectMapper().registerModule(new Jdk8Module()))
)
.handlers(chain ->
chain.get(ctx -> {
Optional<Person> personOptional = Optional.of(new Person("John"));
ctx.render(json(personOptional));
})
)
).test(httpClient -> {
ReceivedResponse response = httpClient.get();
assertEquals("{\"name\":\"John\"}", response.getBody().getText());
assertEquals("application/json", response.getBody().getContentType().getType());
});
}
}
Modifier and Type | Method and Description |
---|---|
static <T> ResponseChunks |
chunkedJsonList(ObjectWriter objectWriter,
Publisher<T> stream)
Renders a data stream as a JSON list, directly streaming the JSON.
|
static <T> ResponseChunks |
chunkedJsonList(Registry registry,
Publisher<T> stream)
Renders a data stream as a JSON list, directly streaming the JSON.
|
static <T> Parse<T,JsonParseOpts> |
fromJson(java.lang.Class<T> type)
Creates a
parseable object to parse a request body into the given type. |
static <T> Parse<T,JsonParseOpts> |
fromJson(java.lang.Class<T> type,
ObjectMapper objectMapper)
Creates a
parseable object to parse a request body into the given type. |
static <T> Parse<T,JsonParseOpts> |
fromJson(TypeToken<T> type)
Creates a
parseable object to parse a request body into the given type. |
static <T> Parse<T,JsonParseOpts> |
fromJson(TypeToken<T> type,
ObjectMapper objectMapper)
Creates a
parseable object to parse a request body into the given type. |
static ObjectWriter |
getObjectWriter(Registry registry) |
static JsonRender |
json(java.lang.Object object)
Creates a
renderable object to render the given object as JSON. |
static JsonRender |
json(java.lang.Object object,
java.lang.Class<?> viewClass)
Creates a
renderable object to render the given object as JSON. |
static JsonRender |
json(java.lang.Object object,
ObjectWriter objectWriter)
Creates a
renderable object to render the given object as JSON. |
static JsonRender |
json(java.lang.Object object,
ObjectWriter objectWriter,
java.lang.Class<?> viewClass)
Creates a
renderable object to render the given object as JSON. |
static Parse<JsonNode,JsonParseOpts> |
jsonNode()
Creates a
parseable object to parse a request body into a JsonNode . |
static Parse<JsonNode,JsonParseOpts> |
jsonNode(ObjectMapper objectMapper)
Creates a
parseable object to parse a request body into a JsonNode . |
static <T> Function<T,java.lang.String> |
toJson(Registry registry)
Creates a mapping function that returns the JSON representation as a string of the input object.
|
public static JsonRender json(java.lang.Object object)
renderable object
to render the given object as JSON.
The given object will be converted to JSON using an ObjectWriter
obtained from the context registry.
See the rendering section for usage examples.
object
- the object to render as JSONpublic static JsonRender json(java.lang.Object object, @Nullable ObjectWriter objectWriter)
renderable object
to render the given object as JSON.
The given object will be converted to JSON using the given ObjectWriter
.
If it is null
, an ObjectWriter
will be obtained from the context registry.
See the rendering section for usage examples.
object
- the object to render as JSONobjectWriter
- the object writer to use to serialize the object to JSONpublic static JsonRender json(java.lang.Object object, @Nullable java.lang.Class<?> viewClass)
renderable object
to render the given object as JSON.
The given object will be converted to JSON using an ObjectWriter
obtained from the context registry
with the specified view Class
used to determine which fields are included.
If it is null the default view rendering of the ObjectWriter
will be used.
See the rendering section for usage examples.
object
- the object to render as JSONviewClass
- the view to use when renderingpublic static JsonRender json(java.lang.Object object, @Nullable ObjectWriter objectWriter, @Nullable java.lang.Class<?> viewClass)
renderable object
to render the given object as JSON.
The given object will be converted to JSON using the given ObjectWriter
with the specified view Class
used to determine which fields are included.
If the ObjectWriter
is null
, an ObjectWriter
will be obtained from the context registry.
If the view Class
is null the default view rendering of the ObjectWriter
will be used.
See the rendering section for usage examples.
object
- the object to render as JSONobjectWriter
- the object writer to use to serialize the object to JSONviewClass
- the view to use when renderingpublic static Parse<JsonNode,JsonParseOpts> jsonNode()
parseable object
to parse a request body into a JsonNode
.
The corresponding parser for this type requires the request content type to be "application/json"
.
The request body will be parsed using an ObjectMapper
obtained from the context registry.
See the parsing section for usage examples.
public static Parse<JsonNode,JsonParseOpts> jsonNode(@Nullable ObjectMapper objectMapper)
parseable object
to parse a request body into a JsonNode
.
The corresponding parser for this type requires the request content type to be "application/json"
.
The request body will be parsed using the given ObjectMapper
.
If it is null
, a mapper will be obtained from the context registry.
See the parsing section for usage examples.
objectMapper
- the object mapper to use to parse the JSONpublic static <T> Parse<T,JsonParseOpts> fromJson(java.lang.Class<T> type)
parseable object
to parse a request body into the given type.
The corresponding parser for this type requires the request content type to be "application/json"
.
The request body will be parsed using an ObjectMapper
obtained from the context registry.
See the parsing section for usage examples.
T
- the type of object to deserialize the JSON intotype
- the type of object to deserialize the JSON intopublic static <T> Parse<T,JsonParseOpts> fromJson(TypeToken<T> type)
parseable object
to parse a request body into the given type.
The corresponding parser for this type requires the request content type to be "application/json"
.
The request body will be parsed using an ObjectMapper
obtained from the context registry.
See the parsing section for usage examples.
T
- the type of object to deserialize the JSON intotype
- the type of object to deserialize the JSON intopublic static <T> Parse<T,JsonParseOpts> fromJson(java.lang.Class<T> type, @Nullable ObjectMapper objectMapper)
parseable object
to parse a request body into the given type.
The corresponding parser for this type requires the request content type to be "application/json"
.
The request body will be parsed using the given ObjectMapper
.
If it is null
, a mapper will be obtained from the context registry.
See the parsing section for usage examples.
T
- the type of object to deserialize the JSON intotype
- the type of object to deserialize the JSON intoobjectMapper
- the object mapper to use to convert the JSON into a Java objectpublic static <T> Parse<T,JsonParseOpts> fromJson(TypeToken<T> type, @Nullable ObjectMapper objectMapper)
parseable object
to parse a request body into the given type.
The corresponding parser for this type requires the request content type to be "application/json"
.
The request body will be parsed using the given ObjectMapper
.
If it is null
, a mapper will be obtained from the context registry.
See the parsing section for usage examples.
T
- the type of object to deserialize the JSON intotype
- the type of object to deserialize the JSON intoobjectMapper
- the object mapper to use to convert the JSON into a Java objectpublic static <T> ResponseChunks chunkedJsonList(Registry registry, Publisher<T> stream)
This method differs from rendering a list of items using json(someList)
in that data is
written to the response as chunks, and is streamed.
If stream can be very large without using considerable memory as the JSON is streamed incrementally in chunks. This does mean that if on object-to-JSON conversion fails midway through the stream, then the output JSON will be malformed due to being incomplete. If the publisher emits an error, the response will be terminated and no more JSON will be sent.
import ratpack.test.embed.EmbeddedApp;
import ratpack.jackson.Jackson;
import ratpack.http.client.ReceivedResponse;
import ratpack.stream.Streams;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.reactivestreams.Publisher;
import java.util.Arrays;
import static ratpack.jackson.Jackson.chunkedJsonList;
import static org.junit.Assert.*;
public class Example {
public static void main(String... args) throws Exception {
EmbeddedApp.of(s -> s
.handlers(chain ->
chain.get(ctx -> {
Publisher<Integer> ints = Streams.publish(Arrays.asList(1, 2, 3));
ctx.render(chunkedJsonList(ctx, ints));
})
)
).test(httpClient -> {
ReceivedResponse response = httpClient.get();
assertEquals("[1,2,3]", response.getBody().getText()); // body was streamed in chunks
assertEquals("application/json", response.getBody().getContentType().getType());
});
}
}
Items of the stream will be converted to JSON by an ObjectMapper
obtained from the given registry.
This method uses Streams.streamMap(Publisher, StreamMapper)
to consume the given stream.
T
- the type of item in the streamregistry
- the registry to obtain the object mapper fromstream
- the stream to renderStreams.streamMap(Publisher, StreamMapper)
public static ObjectWriter getObjectWriter(Registry registry)
public static <T> ResponseChunks chunkedJsonList(ObjectWriter objectWriter, Publisher<T> stream)
Identical to chunkedJsonList(Registry, Publisher)
, except uses the given object writer instead of obtaining one from the registry.
T
- the type of item in the streamobjectWriter
- the object write to use to convert stream items to their JSON representationstream
- the stream to renderchunkedJsonList(Registry, Publisher)
public static <T> Function<T,java.lang.String> toJson(Registry registry)
An ObjectWriter
instance is obtained from the given registry eagerly.
The returned function uses the ObjectWriter.writeValueAsString(Object)
method to convert the input object to JSON.
import ratpack.exec.Promise;
import ratpack.test.embed.EmbeddedApp;
import ratpack.jackson.Jackson;
import ratpack.http.client.ReceivedResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Arrays;
import static ratpack.jackson.Jackson.toJson;
import static java.util.Collections.singletonMap;
import static org.junit.Assert.*;
public class Example {
public static void main(String... args) throws Exception {
EmbeddedApp.of(s -> s
.handlers(chain -> chain
.get(ctx ->
Promise.value(singletonMap("foo", "bar"))
.map(toJson(ctx))
.then(ctx::render)
)
)
).test(httpClient -> {
assertEquals("{\"foo\":\"bar\"}", httpClient.getText());
});
}
}
Note that in the above example, it would have been better to just render the result of the blocking call.
Doing so would be more convenient and also set the correct "Content-Type"
header.
This method can be useful when sending the JSON somewhere else than directly to the response, or when mapping streams
.
T
- the type of object to convert to JSONregistry
- the registry to obtain the ObjectWriter
from