diff --git a/avaje-jex/pom.xml b/avaje-jex/pom.xml
index e4139c48..cab9c672 100644
--- a/avaje-jex/pom.xml
+++ b/avaje-jex/pom.xml
@@ -48,6 +48,12 @@
true
+
+ io.avaje
+ avaje-jsonb-generator
+ 2.3
+ test
+
diff --git a/avaje-jex/src/main/java/io/avaje/jex/Context.java b/avaje-jex/src/main/java/io/avaje/jex/Context.java
index 4b2f2ba9..cd91cad7 100644
--- a/avaje-jex/src/main/java/io/avaje/jex/Context.java
+++ b/avaje-jex/src/main/java/io/avaje/jex/Context.java
@@ -4,6 +4,7 @@
import static java.util.Collections.emptyMap;
import java.io.InputStream;
+import java.io.OutputStream;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.Iterator;
@@ -294,6 +295,15 @@ default String userAgent() {
*/
Context write(InputStream is);
+ /**
+ * Return the outputStream to write content. It is expected that
+ * the {@link #contentType(String)} has been set prior to obtaining
+ * and writing to the outputStream.
+ *
+ * @return The outputStream to write content to.
+ */
+ OutputStream outputStream();
+
/**
* Render a template typically as html.
*
diff --git a/avaje-jex/src/main/java/io/avaje/jex/jdk/JdkContext.java b/avaje-jex/src/main/java/io/avaje/jex/jdk/JdkContext.java
index cfb34839..c0ffe37d 100644
--- a/avaje-jex/src/main/java/io/avaje/jex/jdk/JdkContext.java
+++ b/avaje-jex/src/main/java/io/avaje/jex/jdk/JdkContext.java
@@ -477,6 +477,7 @@ public String protocol() {
return exchange.getProtocol();
}
+ @Override
public OutputStream outputStream() {
var out = mgr.createOutputStream(this);
if (compressionConfig.compressionEnabled()) {
diff --git a/avaje-jex/src/test/java/io/avaje/jex/jdk/HelloDto.java b/avaje-jex/src/test/java/io/avaje/jex/jdk/HelloDto.java
index e8861f3f..a352e742 100644
--- a/avaje-jex/src/test/java/io/avaje/jex/jdk/HelloDto.java
+++ b/avaje-jex/src/test/java/io/avaje/jex/jdk/HelloDto.java
@@ -1,5 +1,8 @@
package io.avaje.jex.jdk;
+import io.avaje.jsonb.Json;
+
+@Json
public class HelloDto {
public long id;
diff --git a/avaje-jex/src/test/java/io/avaje/jex/jdk/JsonTest.java b/avaje-jex/src/test/java/io/avaje/jex/jdk/JsonTest.java
index 1ab2dcab..a7fc591a 100644
--- a/avaje-jex/src/test/java/io/avaje/jex/jdk/JsonTest.java
+++ b/avaje-jex/src/test/java/io/avaje/jex/jdk/JsonTest.java
@@ -11,6 +11,8 @@
import java.util.concurrent.locks.LockSupport;
import java.util.stream.Stream;
+import io.avaje.jsonb.JsonType;
+import io.avaje.jsonb.Jsonb;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
@@ -26,12 +28,19 @@ private static AutoCloseIterator createBeanIterator() {
return new AutoCloseIterator<>(HELLO_BEANS.iterator());
}
- static TestPair pair = init();
+ static final TestPair pair = init();
+ static final Jsonb jsonb = Jsonb.builder().build();
+ static final JsonType jsonTypeHelloDto = jsonb.type(HelloDto.class);
static TestPair init() {
Jex app = Jex.create()
.routing(routing -> routing
- .get("/", ctx -> ctx.json(HelloDto.rob()).status(200))
+ .get("/", ctx -> ctx.status(200).json(HelloDto.rob()))
+ .get("/usingOutputStream", ctx -> {
+ ctx.status(200).contentType("application/json");
+ var result = HelloDto.rob();
+ jsonTypeHelloDto.toJson(result, ctx.outputStream());
+ })
.get("/iterate", ctx -> ctx.jsonStream(ITERATOR))
.get("/stream", ctx -> ctx.jsonStream(HELLO_BEANS.stream()))
.post("/", ctx -> ctx.text("bean[" + ctx.bodyAsClass(HelloDto.class) + "]")));
@@ -58,9 +67,33 @@ void get() {
.GET().asString();
final HttpHeaders headers = hres.headers();
- assertThat(headers.firstValue("Content-Type").get()).isEqualTo("application/json");
+ assertThat(headers.firstValue("Content-Type").orElseThrow()).isEqualTo("application/json");
}
+ @Test
+ void usingOutputStream() {
+
+ var bean = pair.request().path("usingOutputStream")
+ .GET()
+ .bean(HelloDto.class);
+
+ assertThat(bean.id).isEqualTo(42);
+ assertThat(bean.name).isEqualTo("rob");
+
+ final HttpResponse hres = pair.request()
+ .GET().asString();
+
+ final HttpHeaders headers = hres.headers();
+ assertThat(headers.firstValue("Content-Type").orElseThrow()).isEqualTo("application/json");
+
+ bean = pair.request().path("usingOutputStream")
+ .GET()
+ .bean(HelloDto.class);
+ assertThat(bean.id).isEqualTo(42);
+ assertThat(bean.name).isEqualTo("rob");
+ }
+
+
@Test
void stream_viaIterator() {
final Stream beanStream = pair.request()