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

sangria.marshalling.argonaut.scala Maven / Gradle / Ivy

package sangria.marshalling

import _root_.argonaut._
import _root_.argonaut.Argonaut._

import scala.util.{Success, Failure}

object argonaut {
  implicit object ArgonautResultMarshaller extends ResultMarshaller {
    type Node = Json
    type MapBuilder = ArrayMapBuilder[Node]

    def emptyMapNode(keys: Seq[String]) = new ArrayMapBuilder[Node](keys)
    def addMapNodeElem(builder: MapBuilder, key: String, value: Node, optional: Boolean) = builder.add(key, value)

    def mapNode(builder: MapBuilder) = Json.obj(builder.toSeq: _*)
    def mapNode(keyValues: Seq[(String, Json)]) = Json.obj(keyValues: _*)

    def arrayNode(values: Vector[Json]) = Json.array(values: _*)
    def optionalArrayNodeValue(value: Option[Json]) = value match {
      case Some(v) ⇒ v
      case None ⇒ nullNode
    }

    def scalarNode(value: Any, typeName: String, info: Set[ScalarValueInfo]) = value match {
      case v: String ⇒ Json.jString(v)
      case v: Boolean ⇒ Json.jBool(v)
      case v: Int ⇒ Json.jNumber(v)
      case v: Long ⇒ Json.jNumber(v)
      case v: Float ⇒ Json.jNumber(v).get
      case v: Double ⇒ Json.jNumber(v).get
      case v: BigInt ⇒ Json.jNumber(BigDecimal(v))
      case v: BigDecimal ⇒ Json.jNumber(v)
      case v ⇒ throw new IllegalArgumentException("Unsupported scalar value: " + v)
    }

    def enumNode(value: String, typeName: String) = Json.jString(value)

    def nullNode = Json.jNull

    def renderCompact(node: Json) = node.nospaces
    def renderPretty(node: Json) = node.spaces2
  }

  implicit object ArgonautMarshallerForType extends ResultMarshallerForType[Json] {
    val marshaller = ArgonautResultMarshaller
  }

  implicit object ArgonautInputUnmarshaller extends InputUnmarshaller[Json] {
    def getRootMapValue(node: Json, key: String) = node.obj.get(key)

    def isMapNode(node: Json) = node.isObject
    def getMapValue(node: Json, key: String) = node.obj.get(key)
    def getMapKeys(node: Json) = node.obj.get.fields

    def isListNode(node: Json) = node.isArray
    def getListValue(node: Json) = node.array.get

    def isDefined(node: Json) = !node.isNull
    def getScalarValue(node: Json) =
      if (node.isBool)
        node.bool.get
      else if (node.isNumber) {
        val num = node.number.get.toBigDecimal

        num.toBigIntExact getOrElse num
      } else if (node.isString)
        node.string.get
      else
        throw new IllegalStateException(s"$node is not a scalar value")

    def getScalaScalarValue(node: Json) = getScalarValue(node)

    def isEnumNode(node: Json) = node.isString

    def isScalarNode(node: Json) =
      node.isBool || node.isNumber || node.isString

    def isVariableNode(node: Json) = false
    def getVariableName(node: Json) = throw new IllegalArgumentException("variables are not supported")

    def render(node: Json) = node.nospaces
  }

  implicit object argonautToInput extends ToInput[Json, Json] {
    def toInput(value: Json) = (value, ArgonautInputUnmarshaller)
  }

  implicit object argonautFromInput extends FromInput[Json] {
    val marshaller = ArgonautResultMarshaller
    def fromResult(node: marshaller.Node) = node
  }

  implicit def argonautEncodeJsonToInput[T : EncodeJson]: ToInput[T, Json] =
    new ToInput[T, Json] {
      def toInput(value: T) = implicitly[EncodeJson[T]].apply(value) → ArgonautInputUnmarshaller
    }

  implicit def argonautDecoderFromInput[T : DecodeJson]: FromInput[T] =
    new FromInput[T] {
      val marshaller = ArgonautResultMarshaller
      def fromResult(node: marshaller.Node) =
        implicitly[DecodeJson[T]].decodeJson(node).fold((error, _) ⇒ throw InputParsingError(Vector(error)), identity)
    }

  implicit object ArgonautInputParser extends InputParser[Json] {
    def parse(str: String) = str.decodeEither[Json].fold(error ⇒ Failure(ArgonautParsingException(error)), Success(_))
  }

  case class ArgonautParsingException(message: String) extends Exception(message)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy