All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.fxhibon.json.derived.ReadsDerivation.scala Maven / Gradle / Ivy

The newest version!
package com.github.fxhibon.json.derived

import com.github.fxhibon.json.derived.config.{PayloadPath, TypeNameReads}
import magnolia._
import play.api.libs.json._

import scala.language.experimental.macros

object ReadsDerivation {

  type Typeclass[T] = Reads[T]

  def combine[T](ctx: CaseClass[Reads, T]): Reads[T] =
    (value: JsValue) => {
      ctx.constructEither { param =>
        (JsPath \ param.label).read(param.typeclass).reads(value) match {
          case JsSuccess(value, _) => Right(value)
          case JsError(errors) => Left(errors)
        }
      } match {
        case Left(value) => JsError(value.flatten)
        case Right(value) => JsSuccess(value)
      }
    }

  def dispatch[T](
      ctx: SealedTrait[Reads, T]
  )(implicit
      typeNameReads: TypeNameReads = TypeNameReads.defaultTypeNameReads,
      payloadPath: PayloadPath = PayloadPath.defaultPayloadPath
  ): Reads[T] =
    (value: JsValue) => {
      typeNameReads.reads
        .flatMap { typeName =>
          ctx.subtypes.find(_.typeName.short == typeName) match {
            case Some(subtype) =>
              Reads[T](_ => payloadPath.path.read(subtype.typeclass).reads(value))
            case None =>
              Reads[T](_ => JsError("error.invalid.typename"))
          }
        }
        .reads(value)
    }

  implicit def deriveReads[T]: Reads[T] = macro Magnolia.gen[T]

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy