Skip to content

Instantly share code, notes, and snippets.

@rozza
Forked from piotrga/Json.scala
Created June 18, 2013 10:57
Show Gist options
  • Save rozza/5804417 to your computer and use it in GitHub Desktop.
Save rozza/5804417 to your computer and use it in GitHub Desktop.
import util.parsing.json.JSON
import io.Source
import scala.language.dynamics
object Example extends App{
val json = """{
"name" : "Adam Slodowy",
"active": "true",
"roles" : [ "teacher", "admin" ],
"lessons" : [ { "id": 1 }, { "id": 2 } ],
"security" : { "id" : 123, "login": "adams" }
}"""
val adam = JsonElement.parse(json).get
case class Lesson(teacher: String, id: Int, name: String, active : Boolean = true)
val lesson = Lesson(adam.name, adam.lessons.at(1).id, adam.lessons.at(1).name, adam.active)
// will create Lesson("Adam Slodowy", 2, "", true ) - see the implicit conversions
}
trait JsonElement extends Dynamic{ self =>
def selectDynamic(field: String) : JsonElement = EmptyElement
def applyDynamic(field: String)(i: Int) : JsonElement = EmptyElement
def toList : List[String] = sys.error(s"$this is not a list.")
def asString: String = sys.error(s"$this has no string representation.")
def length$ : Int = sys.error(s"$this has no length")
}
object JsonElement{
def ^(s: String) = {
require(!s.isEmpty, "Element is empty")
s
}
implicit def toString(e: JsonElement) : String = e.asString
implicit def toBoolean(e: JsonElement) : Boolean = (^(e.asString)).toBoolean
implicit def toBigDecimal(e: JsonElement) : BigDecimal = BigDecimal(^(e.asString))
implicit def toDouble(e: JsonElement) : Double = ^(e.asString).toDouble
implicit def toFloat(e: JsonElement) : Float = ^(e.asString).toFloat
implicit def toByte(e: JsonElement) : Byte = ^(e.asString).stripSuffix(".0").toByte
implicit def toShort(e: JsonElement) : Short = ^(e.asString).stripSuffix(".0").toShort
implicit def toInt(e: JsonElement) : Int = ^(e.asString).stripSuffix(".0").toInt
implicit def toLong(e: JsonElement) : Long = ^(e.asString).stripSuffix(".0").toLong
implicit def toList(e: JsonElement) : List[String] = e.toList
def parse(json: String) = JSON.parseFull(json) map (JsonElement(_))
def apply(any : Any) : JsonElement = any match {
case x : Seq[Any] => new ArrayElement(x)
case x : Map[String, Any] => new ComplexElement(x)
case x => new PrimitiveElement(x)
}
}
case class PrimitiveElement(x: Any) extends JsonElement{
override def asString = x.toString
}
case object EmptyElement extends JsonElement{
override def asString = ""
override def toList = Nil
}
case class ArrayElement(private val x: Seq[Any]) extends JsonElement{
private lazy val elements = x.map((JsonElement(_))).toArray
override def applyDynamic(field: String)(i: Int) : JsonElement = elements.lift(i).getOrElse(EmptyElement)
override def toList : List[String] = elements map (_.asString) toList
override def length$ : Int = elements.length
}
case class ComplexElement(private val fields : Map[String, Any]) extends JsonElement{
override def selectDynamic(field: String) : JsonElement = fields.get(field) map(JsonElement(_)) getOrElse(EmptyElement)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment