summaryrefslogtreecommitdiff
path: root/src/main/scala/cc
diff options
context:
space:
mode:
authorMathias <mathias@spray.cc>2011-12-06 13:22:37 +0100
committerMathias <mathias@spray.cc>2011-12-06 13:23:02 +0100
commit94b1fba92d40568c642a0b86c719c4bcc0865b54 (patch)
tree0c9a278e636426f99435b7e4f155cc2fe03495ff /src/main/scala/cc
parent701be7bcf0a295c3de272a11e7cfb477db7ed026 (diff)
downloadspray-json-94b1fba92d40568c642a0b86c719c4bcc0865b54.tar.gz
spray-json-94b1fba92d40568c642a0b86c719c4bcc0865b54.tar.bz2
spray-json-94b1fba92d40568c642a0b86c719c4bcc0865b54.zip
Remove JsField, turn JsObject(List[JsField]) into JsObject(Map[String, JsValue])
Diffstat (limited to 'src/main/scala/cc')
-rw-r--r--src/main/scala/cc/spray/json/CollectionFormats.scala9
-rw-r--r--src/main/scala/cc/spray/json/CompactPrinter.scala6
-rw-r--r--src/main/scala/cc/spray/json/DeserializationException.scala2
-rw-r--r--src/main/scala/cc/spray/json/JsValue.scala21
-rw-r--r--src/main/scala/cc/spray/json/JsonParser.scala4
-rw-r--r--src/main/scala/cc/spray/json/PrettyPrinter.scala6
-rw-r--r--src/main/scala/cc/spray/json/ProductFormats.scala28
-rw-r--r--src/main/scala/cc/spray/json/package.scala2
8 files changed, 37 insertions, 41 deletions
diff --git a/src/main/scala/cc/spray/json/CollectionFormats.scala b/src/main/scala/cc/spray/json/CollectionFormats.scala
index a17c43f..c6c3403 100644
--- a/src/main/scala/cc/spray/json/CollectionFormats.scala
+++ b/src/main/scala/cc/spray/json/CollectionFormats.scala
@@ -47,15 +47,16 @@ trait CollectionFormats {
*/
implicit def mapFormat[K :JsonFormat, V :JsonFormat] = new RootJsonFormat[Map[K, V]] {
def write(m: Map[K, V]) = JsObject {
- m.toList.map { t =>
- t._1.toJson match {
- case JsString(x) => JsField(x, t._2.toJson)
+ m.map { field =>
+ field._1.toJson match {
+ case JsString(x) => x -> field._2.toJson
case x => throw new SerializationException("Map key must be formatted as JsString, not '" + x + "'")
}
}
}
def read(value: JsValue) = value match {
- case JsObject(fields) => fields.map(field => (JsString(field.name).convertTo[K], field.value.convertTo[V])).toMap
+ case JsObject(fields) =>
+ fields.map(field => (JsString(field._1).convertTo[K], field._2.convertTo[V])) (collection.breakOut)
case x => throw new DeserializationException("Expected Map as JsObject, but got " + x)
}
}
diff --git a/src/main/scala/cc/spray/json/CompactPrinter.scala b/src/main/scala/cc/spray/json/CompactPrinter.scala
index 329c08e..467160d 100644
--- a/src/main/scala/cc/spray/json/CompactPrinter.scala
+++ b/src/main/scala/cc/spray/json/CompactPrinter.scala
@@ -31,12 +31,12 @@ trait CompactPrinter extends JsonPrinter {
}
}
- private def printObject(members: List[JsField], sb: StringBuilder) {
+ private def printObject(members: Map[String, JsValue], sb: StringBuilder) {
sb.append('{')
printSeq(members, sb.append(',')) { m =>
- printString(m.name, sb)
+ printString(m._1, sb)
sb.append(':')
- print(m.value, sb)
+ print(m._2, sb)
}
sb.append('}')
}
diff --git a/src/main/scala/cc/spray/json/DeserializationException.scala b/src/main/scala/cc/spray/json/DeserializationException.scala
index 283d996..b317a14 100644
--- a/src/main/scala/cc/spray/json/DeserializationException.scala
+++ b/src/main/scala/cc/spray/json/DeserializationException.scala
@@ -16,4 +16,4 @@
package cc.spray.json
-class DeserializationException(msg: String) extends RuntimeException(msg) \ No newline at end of file
+class DeserializationException(msg: String, cause: Throwable = null) extends RuntimeException(msg, cause) \ No newline at end of file
diff --git a/src/main/scala/cc/spray/json/JsValue.scala b/src/main/scala/cc/spray/json/JsValue.scala
index cc1af91..f4dbf91 100644
--- a/src/main/scala/cc/spray/json/JsValue.scala
+++ b/src/main/scala/cc/spray/json/JsValue.scala
@@ -18,7 +18,9 @@
package cc.spray.json
-import collection.mutable.ListBuffer
+import collection.mutable.{LinkedHashMap, ListBuffer}
+import collection.immutable.ListMap
+
/**
* The general type of a JSON AST node.
@@ -37,23 +39,14 @@ sealed trait JsValue {
/**
* A JSON object.
*/
-case class JsObject(fields: List[JsField]) extends JsValue {
- lazy val asMap: Map[String, JsValue] = {
- val b = Map.newBuilder[String, JsValue]
- for (JsField(name, value) <- fields) b += ((name, value))
- b.result()
- }
-}
+case class JsObject(fields: Map[String, JsValue]) extends JsValue
object JsObject {
- def apply(members: JsField*) = new JsObject(members.toList)
+ // we use a ListMap in order to preserve the field order
+ def apply(members: JsField*) = new JsObject(ListMap(members: _*))
+ def apply(members: List[JsField]) = new JsObject(ListMap(members: _*))
}
/**
- * The members/fields of a JSON object.
- */
-case class JsField(name: String, value: JsValue) extends JsValue
-
-/**
* A JSON array.
*/
case class JsArray(elements: List[JsValue]) extends JsValue
diff --git a/src/main/scala/cc/spray/json/JsonParser.scala b/src/main/scala/cc/spray/json/JsonParser.scala
index b93a9a6..21b1d68 100644
--- a/src/main/scala/cc/spray/json/JsonParser.scala
+++ b/src/main/scala/cc/spray/json/JsonParser.scala
@@ -31,10 +31,10 @@ object JsonParser extends Parser {
def Json = rule { WhiteSpace ~ Value ~ EOI }
def JsonObject: Rule1[JsObject] = rule {
- "{ " ~ zeroOrMore(Pair, separator = ", ") ~ "} " ~~> (JsObject(_))
+ "{ " ~ zeroOrMore(Pair, separator = ", ") ~ "} " ~~> (JsObject(_ :_*))
}
- def Pair = rule { JsonStringUnwrapped ~ ": " ~ Value ~~> (JsField(_, _)) }
+ def Pair = rule { JsonStringUnwrapped ~ ": " ~ Value ~~> ((_, _)) }
def Value: Rule1[JsValue] = rule {
JsonString | JsonNumber | JsonObject | JsonArray | JsonTrue | JsonFalse | JsonNull
diff --git a/src/main/scala/cc/spray/json/PrettyPrinter.scala b/src/main/scala/cc/spray/json/PrettyPrinter.scala
index 93ac0b6..429c984 100644
--- a/src/main/scala/cc/spray/json/PrettyPrinter.scala
+++ b/src/main/scala/cc/spray/json/PrettyPrinter.scala
@@ -37,13 +37,13 @@ trait PrettyPrinter extends JsonPrinter {
}
}
- private def printObject(members: List[JsField], sb: StringBuilder, indent: Int) {
+ private def printObject(members: Map[String, JsValue], sb: StringBuilder, indent: Int) {
sb.append("{\n")
printSeq(members, sb.append(",\n")) { m =>
printIndent(sb, indent + Indent)
- printString(m.name, sb)
+ printString(m._1, sb)
sb.append(": ")
- print(m.value, sb, indent + Indent)
+ print(m._2, sb, indent + Indent)
}
sb.append('\n')
printIndent(sb, indent)
diff --git a/src/main/scala/cc/spray/json/ProductFormats.scala b/src/main/scala/cc/spray/json/ProductFormats.scala
index 90c3349..810a6ec 100644
--- a/src/main/scala/cc/spray/json/ProductFormats.scala
+++ b/src/main/scala/cc/spray/json/ProductFormats.scala
@@ -401,24 +401,24 @@ trait ProductFormats {
val value = p.productElement(ix).asInstanceOf[T]
writer match {
case _: OptionFormat[_] if (value == None) => rest
- case _ => JsField(fieldName, writer.write(value)) :: rest
+ case _ => (fieldName, writer.write(value)) :: rest
}
}
private def fromField[T](value: JsValue, fieldName: String)(implicit reader: JsonReader[T]) = {
- @tailrec
- def getFrom(fields: List[JsField]): T = {
- if (fields.isEmpty) {
- if (reader.isInstanceOf[OptionFormat[_]]) None.asInstanceOf[T]
- else throw new DeserializationException("Object is missing required member '" + fieldName + "'")
- } else if (fields.head.name == fieldName) {
- reader.read(fields.head.value)
- } else {
- getFrom(fields.tail)
- }
- }
value match {
- case x: JsObject => getFrom(x.fields)
+ case x: JsObject =>
+ var fieldFound = false
+ try {
+ val fieldValue = x.fields(fieldName)
+ fieldFound = true
+ reader.read(fieldValue)
+ }
+ catch {
+ case e: NoSuchElementException if !fieldFound =>
+ if (reader.isInstanceOf[OptionFormat[_]]) None.asInstanceOf[T]
+ else throw new DeserializationException("Object is missing required member '" + fieldName + "'", e)
+ }
case _ => throw new DeserializationException("Object expected")
}
}
@@ -437,6 +437,6 @@ trait NullOptions extends ProductFormats {
override protected def productElement2Field[T](fieldName: String, p: Product, ix: Int, rest: List[JsField])
(implicit writer: JsonWriter[T]) = {
val value = p.productElement(ix).asInstanceOf[T]
- JsField(fieldName, writer.write(value)) :: rest
+ (fieldName, writer.write(value)) :: rest
}
} \ No newline at end of file
diff --git a/src/main/scala/cc/spray/json/package.scala b/src/main/scala/cc/spray/json/package.scala
index ee50ec0..f080312 100644
--- a/src/main/scala/cc/spray/json/package.scala
+++ b/src/main/scala/cc/spray/json/package.scala
@@ -17,6 +17,8 @@
package cc.spray
package object json {
+
+ type JsField = (String, JsValue)
def jsonReader[T](implicit reader: JsonReader[T]) = reader
def jsonWriter[T](implicit writer: JsonWriter[T]) = writer