Skip to content

Instantly share code, notes, and snippets.

@guizmaii
Created August 4, 2020 04:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guizmaii/6687a5a2b4d82b84314ab63c9929ec9b to your computer and use it in GitHub Desktop.
Save guizmaii/6687a5a2b4d82b84314ab63c9929ec9b to your computer and use it in GitHub Desktop.
package spray.json
import cats.Show
import io.circe.Decoder.Result
import io.circe.{Codec, DecodingFailure, HCursor, Json}
import scala.util.control.NonFatal
trait CorrectDefaultJsonProtocol extends DefaultJsonProtocol {
implicit final val show: Show[JsValue] = _.compactPrint
/*_*/
override implicit def optionFormat[T: JF]: JF[Option[T]] = new CorrectOptionFormat[T]
/*_*/
/**
* Without this fix, it's not possible to correctly serialize some JSON to this:
*
* final case class Foo(value: Option[NonEmptyString])
*/
class CorrectOptionFormat[T: JsonFormat] extends OptionFormat[T] {
override def read(value: JsValue): Option[T] =
value match {
case JsNull => None
case x =>
try Some(x.convertTo[T])
catch {
case NonFatal(_) => None
}
}
}
}
object CorrectDefaultJsonProtocol extends CorrectDefaultJsonProtocol {
implicit final def circeCodecFromSprayJsonFormat[T: JsonFormat]: Codec[T] =
new Codec[T] {
private final def transform(jsValue: JsValue): Json =
jsValue match {
case JsObject(fields: Map[String, JsValue]) => Json.fromFields(fields.view.mapValues(transform))
case JsArray(elements: Seq[JsValue]) => Json.fromValues(elements.map(transform))
case JsString(value: String) => Json.fromString(value)
case JsNumber(value: BigDecimal) => Json.fromBigDecimal(value)
case JsBoolean(value: Boolean) => Json.fromBoolean(value)
case JsNull => Json.Null
}
override def apply(a: T): Json = transform(a.toJson)
override def apply(c: HCursor): Result[T] =
c.as[Json].flatMap { raw =>
try Right(raw.toString.parseJson.convertTo[T])
catch {
case NonFatal(e) => Left(DecodingFailure(e.getMessage, c.history))
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment