Skip to content

Commit

Permalink
Replace Buf -> String -> Case Class conversions with Buf -> Case Clas…
Browse files Browse the repository at this point in the history
…s conversions in most JSON Decoders.
  • Loading branch information
rpless committed Nov 19, 2016
1 parent 77deb10 commit 7f464cf
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 32 deletions.
12 changes: 6 additions & 6 deletions argonaut/src/main/scala/io/finch/argonaut/Decoders.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.finch.argonaut

import argonaut.{CursorHistory, DecodeJson, Json}
import com.twitter.io.{Buf, Charsets}
import com.twitter.util.{Return, Throw, Try}
import io.finch._
import io.finch.internal.BufText
Expand All @@ -16,12 +17,11 @@ trait Decoders {
implicit def decodeArgonaut[A](implicit d: DecodeJson[A]): Decode.Json[A] =
Decode.json { (b, cs) =>
val err: (String, CursorHistory) => Try[A] = { (str, hist) => Throw[A](Error(str)) }

// TODO: Eliminate toString conversion
// See https://github.com/finagle/finch/issues/511
// Jawn can parse from ByteBuffer's if they represent UTF-8 strings.
// We can check the charset here and do parsing w/o extra to-string conversion.
Parser.parseFromString[Json](BufText.extract(b, cs))(facade) match {
val attemptJson = cs match {
case Charsets.Utf8 => Parser.parseFromByteBuffer[Json](Buf.ByteBuffer.Shared.extract(b))(facade)
case _ => Parser.parseFromString[Json](BufText.extract(b, cs))(facade)
}
attemptJson match {
case Success(value) => d.decodeJson(value).fold[Try[A]](err, Return(_))
case Failure(error) => Throw[A](Error(error.getMessage))
}
Expand Down
21 changes: 9 additions & 12 deletions circe/src/main/scala/io/finch/circe/Decoders.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package io.finch.circe

import cats.syntax.show._
import com.twitter.io.{Buf, Charsets}
import com.twitter.util.{Return, Throw, Try}
import io.circe.Decoder
import io.circe.jawn.decode
import io.circe.jawn._
import io.finch.{Decode, Error}
import io.finch.internal.BufText

Expand All @@ -12,15 +13,11 @@ trait Decoders {
/**
* Maps a Circe's [[Decoder]] to Finch's [[Decode]].
*/
implicit def decodeCirce[A: Decoder]: Decode.Json[A] = Decode.json((b, cs) =>

// TODO: Eliminate toString conversion
// See https://github.com/finagle/finch/issues/511
// Jawn can parse from ByteBuffer's if they represent UTF-8 strings.
// We can check the charset here and do parsing w/o extra to-string conversion.
decode[A](BufText.extract(b, cs)).fold[Try[A]](
error => Throw[A](Error(error.show)),
value => Return(value)
)
)
implicit def decodeCirce[A: Decoder]: Decode.Json[A] = Decode.json({ (b, cs) =>
val attemptJson = cs match {
case Charsets.Utf8 => parseByteBuffer(Buf.ByteBuffer.Shared.extract(b)).right.flatMap(_.as[A])
case _ => decode[A](BufText.extract(b, cs))
}
attemptJson.fold[Try[A]](error => Throw[A](Error(error.show)), value => Return(value))
})
}
9 changes: 3 additions & 6 deletions jackson/src/main/scala/io/finch/jackson/package.scala
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package io.finch

import scala.reflect.ClassTag

import com.fasterxml.jackson.databind.ObjectMapper
import com.twitter.io.Buf
import com.twitter.util.Try
import io.finch.internal.BufText
import scala.reflect.ClassTag

package object jackson {

implicit def decodeJackson[A](implicit
mapper: ObjectMapper, ct: ClassTag[A]
): Decode.Json[A] = Decode.json((b, cs) =>
// TODO: Eliminate toString conversion
// See https://github.com/finagle/finch/issues/511
// Jackson can parse from byte[] automatically detecting the encoding.
Try(mapper.readValue(BufText.extract(b, cs), ct.runtimeClass.asInstanceOf[Class[A]]))
Try(mapper.readValue(Buf.ByteArray.Shared.extract(b), ct.runtimeClass.asInstanceOf[Class[A]]))
)

implicit def encodeJackson[A](implicit mapper: ObjectMapper): Encode.Json[A] =
Expand Down
6 changes: 2 additions & 4 deletions playjson/src/main/scala/io/finch/playjson/package.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.finch

import com.twitter.io.Buf
import com.twitter.util.Try
import io.finch.internal.BufText
import play.api.libs.json._
Expand All @@ -11,10 +12,7 @@ package object playjson {
* @tparam A the type of the data to decode into
*/
implicit def decodePlayJson[A](implicit reads: Reads[A]): Decode.Json[A] =
// TODO: Eliminate toString conversion
// See https://github.com/finagle/finch/issues/511
// PlayJson can parse from byte[] automatically detecting the charset.
Decode.json((b, cs) => Try(Json.parse(BufText.extract(b, cs)).as[A]))
Decode.json((b, cs) => Try(Json.parse(Buf.ByteArray.Shared.extract(b)).as[A]))

/**
* @param writes Play JSON `Writes` to use for encoding
Expand Down
11 changes: 7 additions & 4 deletions sprayjson/src/main/scala/io/finch/sprayjson/package.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.finch

import com.twitter.io.{Buf, Charsets}
import com.twitter.util.Try
import io.finch.internal.BufText
import spray.json._
Expand All @@ -11,10 +12,12 @@ package object sprayjson{
* @tparam A the type of the data to decode into
*/
implicit def decodeSpray[A](implicit format: JsonFormat[A]): Decode.Json[A] =
// TODO: Eliminate toString conversion
// See https://github.com/finagle/finch/issues/511
// SprayJson can parse from byte[] if it represents a UTF-8 string.
Decode.json((b, cs) => Try(BufText.extract(b, cs).parseJson.convertTo[A]))
Decode.json({ (b, cs) =>
cs match {
case Charsets.Utf8 => Try(JsonParser(Buf.ByteArray.Shared.extract(b)).convertTo[A])
case _ => Try(BufText.extract(b, cs).parseJson.convertTo[A])
}
})

/**
* @param format spray-json support for convert JSON val to specific type object
Expand Down

0 comments on commit 7f464cf

Please sign in to comment.