diff --git a/modules/core/src/main/scala/tethys/commons/RawJson.scala b/modules/core/src/main/scala/tethys/commons/RawJson.scala index 26b40093..225a894b 100644 --- a/modules/core/src/main/scala/tethys/commons/RawJson.scala +++ b/modules/core/src/main/scala/tethys/commons/RawJson.scala @@ -20,12 +20,7 @@ object RawJson { ): JsonReader[RawJson] = new JsonReader[RawJson] { override def read( it: TokenIterator - )(implicit fieldName: FieldName): RawJson = { - val stringWriter = new StringWriter() - val tokenWriter: TokenWriter = tokenWriterProducer.forWriter(stringWriter) - JsonStreaming.streamValue(it, tokenWriter) - tokenWriter.flush() - RawJson(stringWriter.toString) - } + )(implicit fieldName: FieldName): RawJson = + RawJson(tokenWriterProducer.withTokenWriter(JsonStreaming.streamValue(it, _))) } } diff --git a/modules/core/src/main/scala/tethys/package.scala b/modules/core/src/main/scala/tethys/package.scala index ca0f45e1..52c4ad32 100644 --- a/modules/core/src/main/scala/tethys/package.scala +++ b/modules/core/src/main/scala/tethys/package.scala @@ -1,4 +1,4 @@ -import java.io.{Reader, StringReader, StringWriter, Writer} +import java.io.{Reader, StringReader} import tethys.readers.{FieldName, ReaderError} import tethys.readers.tokens.{TokenIterator, TokenIteratorProducer} @@ -18,11 +18,8 @@ package object tethys { def asJson(implicit jsonWriter: JsonWriter[A], tokenWriterProducer: TokenWriterProducer - ): String = { - val stringWriter = new StringWriter() - writeJson(tokenWriterProducer.forWriter(stringWriter)) - stringWriter.toString - } + ): String = + tokenWriterProducer.withTokenWriter(jsonWriter.write(a, _)) def asJsonWith( jsonWriter: JsonWriter[A] @@ -31,7 +28,7 @@ package object tethys { } def writeJson( - tokenWriter: TokenWriter + tokenWriter: TokenWriter with TokenWriter.Flushing )(implicit jsonWriter: JsonWriter[A]): Unit = { try jsonWriter.write(a, tokenWriter) finally { @@ -40,12 +37,6 @@ package object tethys { } } - implicit class WriterOps(val w: Writer) extends AnyVal { - def toTokenWriter(implicit - tokenWriterProducer: TokenWriterProducer - ): TokenWriter = tokenWriterProducer.forWriter(w) - } - implicit class StringReaderOps(val json: String) extends AnyVal { def jsonAs[A](implicit jsonReader: JsonReader[A], diff --git a/modules/core/src/main/scala/tethys/writers/tokens/SimpleTokenWriter.scala b/modules/core/src/main/scala/tethys/writers/tokens/SimpleTokenWriter.scala index e72be059..ee5e1828 100644 --- a/modules/core/src/main/scala/tethys/writers/tokens/SimpleTokenWriter.scala +++ b/modules/core/src/main/scala/tethys/writers/tokens/SimpleTokenWriter.scala @@ -7,7 +7,7 @@ import tethys.readers.tokens.TokenIteratorProducer import scala.collection.mutable -class SimpleTokenWriter extends TokenWriter { +class SimpleTokenWriter extends TokenWriter with TokenWriter.Flushing { val tokens: mutable.ArrayBuffer[TokenNode] = mutable.ArrayBuffer.empty override def writeArrayStart(): SimpleTokenWriter.this.type = append( diff --git a/modules/core/src/main/scala/tethys/writers/tokens/TokenWriter.scala b/modules/core/src/main/scala/tethys/writers/tokens/TokenWriter.scala index d1172d0a..e2d08521 100644 --- a/modules/core/src/main/scala/tethys/writers/tokens/TokenWriter.scala +++ b/modules/core/src/main/scala/tethys/writers/tokens/TokenWriter.scala @@ -49,8 +49,11 @@ trait TokenWriter { @throws[UnsupportedOperationException] def writeRawJson(json: String): this.type +} - def close(): Unit - - def flush(): Unit +object TokenWriter { + trait Flushing { + def flush(): Unit + def close(): Unit + } } diff --git a/modules/core/src/main/scala/tethys/writers/tokens/TokenWriterProducer.scala b/modules/core/src/main/scala/tethys/writers/tokens/TokenWriterProducer.scala index a6fbff20..ab000daf 100644 --- a/modules/core/src/main/scala/tethys/writers/tokens/TokenWriterProducer.scala +++ b/modules/core/src/main/scala/tethys/writers/tokens/TokenWriterProducer.scala @@ -1,7 +1,6 @@ package tethys.writers.tokens -import java.io.Writer - trait TokenWriterProducer { - def forWriter(writer: Writer): TokenWriter + type ExactTokenWriter <: TokenWriter + def withTokenWriter(writer: ExactTokenWriter => Unit): String } diff --git a/modules/jackson-backend/src/main/scala/tethys/jackson/JacksonTokenWriter.scala b/modules/jackson-backend/src/main/scala/tethys/jackson/JacksonTokenWriter.scala index 53497f7f..2f65c625 100644 --- a/modules/jackson-backend/src/main/scala/tethys/jackson/JacksonTokenWriter.scala +++ b/modules/jackson-backend/src/main/scala/tethys/jackson/JacksonTokenWriter.scala @@ -3,7 +3,7 @@ package tethys.jackson import com.fasterxml.jackson.core.JsonGenerator import tethys.writers.tokens.TokenWriter -class JacksonTokenWriter(jsonGenerator: JsonGenerator) extends TokenWriter { +class JacksonTokenWriter(jsonGenerator: JsonGenerator) extends TokenWriter with TokenWriter.Flushing { override def writeArrayStart(): JacksonTokenWriter.this.type = { jsonGenerator.writeStartArray() this diff --git a/modules/jackson-backend/src/main/scala/tethys/jackson/package.scala b/modules/jackson-backend/src/main/scala/tethys/jackson/package.scala index 78720394..4cfefdf2 100644 --- a/modules/jackson-backend/src/main/scala/tethys/jackson/package.scala +++ b/modules/jackson-backend/src/main/scala/tethys/jackson/package.scala @@ -2,7 +2,7 @@ package tethys import java.io.{Reader, Writer} -import com.fasterxml.jackson.core.JsonFactory +import com.fasterxml.jackson.core.{JsonFactory, JsonGenerator} import tethys.readers.{FieldName, ReaderError} import tethys.readers.tokens.{TokenIterator, TokenIteratorProducer} import tethys.writers.tokens.{TokenWriter, TokenWriterProducer} @@ -14,14 +14,24 @@ package object jackson { f } - implicit def jacksonTokenWriterProducer(implicit - jsonFactory: JsonFactory = defaultJsonFactory - ): TokenWriterProducer = new TokenWriterProducer { - override def forWriter(writer: Writer): TokenWriter = { - new JacksonTokenWriter(jsonFactory.createGenerator(writer)) + class JacksonTokenWriterProducer( + jsonFactory: JsonFactory, + configure: JsonGenerator => JsonGenerator + ) extends TokenWriterProducer { + type ExactTokenWriter = JacksonTokenWriter + + override def withTokenWriter(write: JacksonTokenWriter => Unit): String = { + val stringWriter = new java.io.StringWriter() + val tw = new JacksonTokenWriter(configure(jsonFactory.createGenerator(stringWriter))) + try write(tw) finally tw.flush() + stringWriter.toString } } + implicit def jacksonTokenWriterProducer(implicit + jsonFactory: JsonFactory = defaultJsonFactory + ): JacksonTokenWriterProducer = new JacksonTokenWriterProducer(jsonFactory, identity) + implicit def jacksonTokenIteratorProducer(implicit jsonFactory: JsonFactory = defaultJsonFactory ): TokenIteratorProducer = new TokenIteratorProducer { diff --git a/modules/jackson-backend/src/main/scala/tethys/jackson/pretty/package.scala b/modules/jackson-backend/src/main/scala/tethys/jackson/pretty/package.scala index 6bb86bd3..9b016391 100644 --- a/modules/jackson-backend/src/main/scala/tethys/jackson/pretty/package.scala +++ b/modules/jackson-backend/src/main/scala/tethys/jackson/pretty/package.scala @@ -9,13 +9,8 @@ import tethys.writers.tokens.{TokenWriter, TokenWriterProducer} package object pretty { implicit def prettyJacksonTokenWriterProducer(implicit jsonFactory: JsonFactory = defaultJsonFactory - ): TokenWriterProducer = new TokenWriterProducer { - override def forWriter(writer: Writer): TokenWriter = { - new JacksonTokenWriter( - jsonFactory.createGenerator(writer).useDefaultPrettyPrinter() - ) - } - } + ): JacksonTokenWriterProducer = + new tethys.jackson.JacksonTokenWriterProducer(jsonFactory, _.useDefaultPrettyPrinter()) implicit def jacksonTokenIteratorProducer(implicit jsonFactory: JsonFactory = defaultJsonFactory diff --git a/modules/jackson-backend/src/test/scala/tethys/jackson/JacksonTokenWriterTest.scala b/modules/jackson-backend/src/test/scala/tethys/jackson/JacksonTokenWriterTest.scala index 290a05d6..7222fee5 100644 --- a/modules/jackson-backend/src/test/scala/tethys/jackson/JacksonTokenWriterTest.scala +++ b/modules/jackson-backend/src/test/scala/tethys/jackson/JacksonTokenWriterTest.scala @@ -1,7 +1,5 @@ package tethys.jackson -import java.io.StringWriter - import org.scalatest.matchers.should.Matchers import org.scalatest.flatspec.AnyFlatSpec import tethys._ @@ -9,13 +7,12 @@ import tethys.writers.tokens.TokenWriter class JacksonTokenWriterTest extends AnyFlatSpec with Matchers { - def iterate(fun: (TokenWriter) => Unit): String = { - val sw = new StringWriter() - val tokenWriter = sw.toTokenWriter - fun(tokenWriter) - tokenWriter.close() - sw.toString - } + def iterate(fun: TokenWriter => Unit): String = + implicitly[JacksonTokenWriterProducer] + .withTokenWriter { tokenWriter => + fun(tokenWriter) + tokenWriter.close() + } behavior of "JacksonTokenWriter"