Created
December 18, 2013 23:11
-
-
Save jcracknell/8031491 to your computer and use it in GitHub Desktop.
Abstracting away your JSON DOM with a 'dialect' mixin.
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
trait JsonDialect { dialect => | |
import scala.language.implicitConversions | |
type JValue | |
type JArray <: JValue | |
type JBoolean <: JValue | |
type JNull <: JValue | |
type JNumber <: JValue | |
type JObject <: JValue | |
type JString <: JValue | |
/** Factory and utility methods for JSON values. | |
* @group Factories */ | |
def JValue: JValueCompanion | |
trait JValueCompanion { | |
/** Decodes a JSON value from the provided string. */ | |
def decode(json: String): JValue | |
/** Decodes a JSON value from the provide [[java.io.Reader]]. */ | |
def decode(reader: java.io.Reader): JValue | |
/** Encodes the provided JSON value to a string. */ | |
def encode(value: JValue): String | |
/** Encodes the provided JSON value to the provided [[java.io.Writer]]. */ | |
def encode(value: JValue, writer: java.io.Writer): Unit | |
def mkArray(elements: Seq[JValue]): JArray | |
def mkBoolean(value: Boolean): JBoolean | |
def mkNumber(value: Double): JNumber | |
def mkObject(properties: Seq[(String, JValue)]): JObject | |
def mkString(value: String): JString | |
def asArray(value: JValue): Option[JArray] | |
def asBoolean(value: JValue): Option[JBoolean] | |
def asNull(value: JValue): Option[JNull] | |
def asNumber(value: JValue): Option[JNumber] | |
def asObject(value: JValue): Option[JObject] | |
def asString(value: JValue): Option[JString] | |
def unpackArray(a: JArray): Seq[JValue] | |
def unpackBoolean(b: JBoolean): Boolean | |
def unpackNumber(n: JNumber): Double | |
def unpackObject(o: JObject): Seq[(String, JValue)] | |
def unpackString(s: JString): String | |
} | |
trait JValueConversion[+A <: JValue] { | |
def apply(value: JValue): Option[A] | |
} | |
object JValueConversion { | |
def apply[A <: JValue](conv: JValue => Option[A]): JValueConversion[A] = | |
new JValueConversion[A] { def apply(value: JValue): Option[A] = conv(value) } | |
implicit val valueConversion: JValueConversion[JValue] = apply(x => Some(x)) | |
implicit val arrayConversion: JValueConversion[JArray] = apply(JValue.asArray) | |
implicit val booleanConversion: JValueConversion[JBoolean] = apply(JValue.asBoolean) | |
implicit val nullConversion: JValueConversion[JNull] = apply(JValue.asNull) | |
implicit val numberConversion: JValueConversion[JNumber] = apply(JValue.asNumber) | |
implicit val objectConversion: JValueConversion[JObject] = apply(JValue.asObject) | |
implicit val stringConversion: JValueConversion[JString] = apply(JValue.asString) | |
} | |
object JArray { | |
def apply(): JArray = JValue.mkArray(Nil) | |
def apply(elements: Seq[JValue]): JArray = JValue.mkArray(elements) | |
def apply(e0: JValue, es: JValue*): JArray = apply(e0 +: es) | |
def unapplySeq(value: JValue): Option[Seq[JValue]] = JValue.asArray(value).map(JValue.unpackArray) | |
} | |
object JBoolean { | |
def apply(value: Boolean): JBoolean = JValue.mkBoolean(value) | |
def unapply(value: JValue): Option[Boolean] = JValue.asBoolean(value).map(JValue.unpackBoolean) | |
} | |
val JNull: JNull | |
object JNumber { | |
def apply(value: Double): JNumber = JValue.mkNumber(value) | |
def unapply(value: JValue): Option[Double] = JValue.asNumber(value).map(JValue.unpackNumber) | |
} | |
object JObject { | |
def apply(): JObject = JValue.mkObject(Nil) | |
def apply(properties: Seq[(String, JValue)]): JObject = JValue.mkObject(properties) | |
def apply(p0: (String, JValue), ps: (String, JValue)*): JObject = apply(p0 +: ps) | |
def unapply(value: JValue): Option[Seq[(String, JValue)]] = JValue.asObject(value).map(JValue.unpackObject) | |
} | |
object JString { | |
def apply(value: String): JString = JValue.mkString(value) | |
def unapply(value: JValue): Option[String] = JValue.asString(value).map(JValue.unpackString) | |
} | |
implicit class JValueOps(value: JValue) { | |
/** Encodes the JSON value to a string. */ | |
def encoded: String = JValue.encode(value) | |
/** Encodes the JSON value to the provided [[java.io.Writer]]. */ | |
def encodeTo(writer: java.io.Writer): Unit = JValue.encode(value, writer) | |
/** Attempt to case the JSON value to the provided dialect type. This method exists in order to enable | |
* conversions using type parameters. */ | |
def as[A <: JValue](implicit conv: JValueConversion[A]): Option[A] = conv(value) | |
/** Attempt to cast the JSON value to the dialect's array type. */ | |
def asArray: Option[JArray] = JValue.asArray(value) | |
/** Attempt to cast the JSON value to the dialect's boolean type. */ | |
def asBoolean: Option[JBoolean] = JValue.asBoolean(value) | |
/** Attempt to cast the JSON value to the dialect's null type. */ | |
def asNull: Option[JNull] = JValue.asNull(value) | |
/** Attempt to cast the JSON value to the dialect's number type. */ | |
def asNumber: Option[JNumber] = JValue.asNumber(value) | |
/** Attempt to cast the JSON value to the dialect's object type. */ | |
def asObject: Option[JObject] = JValue.asObject(value) | |
/** Attempt to cast the JSON value to the dialect's string type. */ | |
def asString: Option[JString] = JValue.asString(value) | |
} | |
/** Operations defined on the dialect's array type. */ | |
implicit class JArrayOps(a: JArray) { | |
/** The JSON array value. */ | |
def value = JValue.unpackArray(a) | |
} | |
/** Operations defined on the dialect's boolean type. */ | |
implicit class JBooleanOps(b: JBoolean) { | |
/** The JSON boolean value. */ | |
def value = JValue.unpackBoolean(b) | |
} | |
/** Operations defined on the dialect's number type. */ | |
implicit class JNumberOps(n: JNumber) { | |
/** The JSON number value. */ | |
def value = JValue.unpackNumber(n) | |
} | |
/** Operations defined on the dialect's object type. */ | |
implicit class JObjectOps(o: JObject) { | |
/** The JSON object value. */ | |
def value = JValue.unpackObject(o) | |
} | |
/** Operations defined on the dialect's string type. */ | |
implicit class JStringOps(s: JString) { | |
/** The JSON string value. */ | |
def value = JValue.unpackString(s) | |
} | |
} |
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
import com.eclipsesource.json._ | |
import scala.collection.JavaConversions._ | |
trait MinimalJsonDialect extends JsonDialect { | |
type JValue = com.eclipsesource.json.JsonValue | |
type JArray = com.eclipsesource.json.JsonArray | |
type JBoolean = com.eclipsesource.json.JsonValue | |
type JNull = com.eclipsesource.json.JsonValue | |
type JNumber = com.eclipsesource.json.JsonValue | |
type JObject = com.eclipsesource.json.JsonObject | |
type JString = com.eclipsesource.json.JsonValue | |
val JNull: JNull = JsonValue.NULL | |
object JValue extends JValueCompanion { | |
def decode(str: String): JValue = JsonValue.readFrom(str) | |
def decode(reader: java.io.Reader): JValue = JsonValue.readFrom(reader) | |
def encode(value: JValue): String = value.toString | |
def encode(value: JValue, writer: java.io.Writer): Unit = value.writeTo(writer) | |
def mkArray(elements: Seq[JValue]): JArray = (new JsonArray /: elements) { (arr, e) => arr.add(e) } | |
def mkBoolean(value: Boolean): JBoolean = if(value) JsonValue.TRUE else JsonValue.FALSE | |
def mkNumber(value: Double): JNumber = JsonValue.valueOf(value) | |
def mkObject(properties: Seq[(String, JValue)]): JObject = (new JsonObject /: properties) { (obj, p) => obj.add(p._1, p._2) } | |
def mkString(value: String): JString = JsonValue.valueOf(value) | |
def asArray(value: JValue): Option[JArray] = if(value.isArray) Some(value.asArray()) else None | |
def asBoolean(value: JValue): Option[JBoolean] = if(value.isBoolean) Some(value.asInstanceOf[JBoolean]) else None | |
def asNull(value: JValue): Option[JNull] = if(value.isNull) Some(value.asInstanceOf[JNull]) else None | |
def asNumber(value: JValue): Option[JNumber] = if(value.isNumber) Some(value.asInstanceOf[JNumber]) else None | |
def asObject(value: JValue): Option[JObject] = if(value.isObject) Some(value.asInstanceOf[JObject]) else None | |
def asString(value: JValue): Option[JString] = if(value.isString) Some(value.asInstanceOf[JString]) else None | |
def unpackArray(a: JArray): Seq[JValue] = a.toSeq | |
def unpackBoolean(b: JBoolean): Boolean = b.isTrue() | |
def unpackNumber(n: JNumber): Double = n.asDouble() | |
def unpackObject(o: JObject): Seq[(String, JValue)] = o.view.map(m => (m.getName, m.getValue)).toSeq | |
def unpackString(s: JString): String = s.asString() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment