Created
August 4, 2020 04:04
-
-
Save guizmaii/6687a5a2b4d82b84314ab63c9929ec9b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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