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

com.rojoma.json.v3.dynamic.DynamicJValue.scala Maven / Gradle / Ivy

The newest version!
package com.rojoma.json.v3
package dynamic

import scala.language.dynamics

import `-impl`.dynamic._
import ast._
import codec.DecodeError
import zipper.{JsonZipper, JArrayZipper, JObjectZipper}

class BadPath(val error: DecodeError.Simple) extends NoSuchElementException(error.english)

sealed trait InformationalDynamicJValue extends Dynamic {
  def ? : Either[DecodeError.Simple, JValue]
  def ! : JValue
  def ^? : Either[DecodeError.Simple, JsonZipper]
  def ^! : JsonZipper

  def apply(idx: Int): InformationalDynamicJValue
  def apply(field: String): InformationalDynamicJValue

  def applyDynamic(field: String) = apply(field)
  def selectDynamic(field: String) = apply(field)
}

object InformationalDynamicJValue extends (JValue => InformationalDynamicJValue) {
  def apply(v: JValue): InformationalDynamicJValue = new Good(JsonZipper(v))

  private class Bad(err: DecodeError.Simple) extends InformationalDynamicJValue {
    def ? = Left(err)
    def ! = throw new BadPath(err)
    def ^? = Left(err)
    def ^! = throw new BadPath(err)

    def apply(idx: Int) = this
    def apply(field: String) = this
  }

  private class Good(zipper : JsonZipper) extends InformationalDynamicJValue {
    def ! = zipper.value : JValue
    def ? = Right(this.!)
    def ^? = Right(zipper)
    def ^! = zipper

    def apply(idx: Int) =
      zipper match {
        case arr: JArrayZipper if arr.value.isDefinedAt(idx) =>
          new Good(arr.down_!(idx))
        case arr: JArrayZipper =>
          new Bad(DecodeError.InvalidLength(expected = idx + 1, got = arr.value.length, path = arr.path))
        case other =>
          new Bad(DecodeError.InvalidType(expected = JArray, got = other.value.jsonType, path = other.path))
      }

    def apply(field: String) =
      zipper match {
        case obj: JObjectZipper =>
          obj.down(field) match {
            case Some(result) =>
              new Good(result)
            case None =>
              new Bad(DecodeError.MissingField(field, zipper.path))
          }
        case other =>
          new Bad(DecodeError.InvalidType(expected = JObject, got = other.value.jsonType, path = other.path))
      }
  }
}

@deprecated(message = "Prefer `InformationalDynamicJValue`", since = "3.1.1")
class DynamicJValue(val ? : Option[JValue]) extends AnyVal with Dynamic {
  def ! =
    ? match {
      case Some(x) => x
      case None => throw new NoSuchElementException("DynamicJValue.static")
    }

  def applyDynamic[T](field: String)(subfieldOrIdx: T)(implicit ev: DynamicPathType[T]): DynamicJValue =
    ? match {
      case Some(JObject(fields)) =>
        fields.get(field) match {
          case Some(item) =>
            item match {
              case obj: JObject if ev.isField =>
                obj.dynamic(ev.asField(subfieldOrIdx))
              case arr: JArray if !ev.isField =>
                arr.dynamic(ev.asIndex(subfieldOrIdx))
              case _=>
                new DynamicJValue(None)
            }
          case None =>
            new DynamicJValue(None)
        }
      case _ =>
        new DynamicJValue(None)
    }

  def selectDynamic(field: String): DynamicJValue =
    apply(field)

  def apply(idx: Int): DynamicJValue =
    ? match {
      case Some(arr: JArray) if arr.isDefinedAt(idx) =>
        arr(idx).dynamic
      case _ =>
        new DynamicJValue(None)
    }

  def apply(field: String): DynamicJValue =
    ? match {
      case Some(obj: JObject) =>
        new DynamicJValue(obj.get(field))
      case _ =>
        new DynamicJValue(None)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy