diff options
author | Mathias <mathias@spray.io> | 2015-05-06 12:02:50 +0200 |
---|---|---|
committer | Mathias <mathias@spray.io> | 2015-05-06 12:41:50 +0200 |
commit | 36a845cb6b889b7255021edf1c891c8c5069b923 (patch) | |
tree | 89da8cc2265d695a935f6b7b8a9117f073841153 | |
parent | 51e1af64175e1c01a0383e6018839fc374bca164 (diff) | |
download | spray-json-36a845cb6b889b7255021edf1c891c8c5069b923.tar.gz spray-json-36a845cb6b889b7255021edf1c891c8c5069b923.tar.bz2 spray-json-36a845cb6b889b7255021edf1c891c8c5069b923.zip |
Introduce `JsObject.empty`, `JsArray.empty`, `JsString.empty` and `JsNumber.zero`, closes #143
-rw-r--r-- | src/main/scala/spray/json/JsValue.scala | 4 | ||||
-rw-r--r-- | src/main/scala/spray/json/JsonParser.scala | 59 |
2 files changed, 40 insertions, 23 deletions
diff --git a/src/main/scala/spray/json/JsValue.scala b/src/main/scala/spray/json/JsValue.scala index 1f9bb05..b21672d 100644 --- a/src/main/scala/spray/json/JsValue.scala +++ b/src/main/scala/spray/json/JsValue.scala @@ -52,6 +52,7 @@ case class JsObject(fields: Map[String, JsValue]) extends JsValue { def getFields(fieldNames: String*): immutable.Seq[JsValue] = fieldNames.flatMap(fields.get)(collection.breakOut) } object JsObject { + val empty = JsObject(Map.empty[String, JsValue]) def apply(members: JsField*) = new JsObject(Map(members: _*)) @deprecated("Use JsObject(JsValue*) instead", "1.3.0") def apply(members: List[JsField]) = new JsObject(Map(members: _*)) @@ -65,6 +66,7 @@ case class JsArray(elements: Vector[JsValue]) extends JsValue { def this(elements: List[JsValue]) = this(elements.toVector) } object JsArray { + val empty = JsArray(Vector.empty) def apply(elements: JsValue*) = new JsArray(elements.toVector) @deprecated("Use JsArray(Vector[JsValue]) instead", "1.3.0") def apply(elements: List[JsValue]) = new JsArray(elements.toVector) @@ -76,6 +78,7 @@ object JsArray { case class JsString(value: String) extends JsValue object JsString { + val empty = JsString("") def apply(value: Symbol) = new JsString(value.name) } @@ -84,6 +87,7 @@ object JsString { */ case class JsNumber(value: BigDecimal) extends JsValue object JsNumber { + val zero: JsNumber = apply(0) def apply(n: Int) = new JsNumber(BigDecimal(n)) def apply(n: Long) = new JsNumber(BigDecimal(n)) def apply(n: Double) = n match { diff --git a/src/main/scala/spray/json/JsonParser.scala b/src/main/scala/spray/json/JsonParser.scala index 674d8ea..bed8dbd 100644 --- a/src/main/scala/spray/json/JsonParser.scala +++ b/src/main/scala/spray/json/JsonParser.scala @@ -16,10 +16,10 @@ package spray.json +import scala.annotation.{switch, tailrec} import java.lang.{StringBuilder => JStringBuilder} import java.nio.{CharBuffer, ByteBuffer} import java.nio.charset.Charset -import scala.annotation.{switch, tailrec} /** * Fast, no-dependency parser for JSON as defined by http://tools.ietf.org/html/rfc4627. @@ -59,7 +59,7 @@ class JsonParser(input: ParserInput) { case '{' => advance(); `object`() case '[' => advance(); `array`() case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '-' => `number`() - case '"' => `string`(); jsValue = JsString(sb.toString) + case '"' => `string`(); jsValue = if (sb.length == 0) JsString.empty else JsString(sb.toString) case _ => fail("JSON Value") } } @@ -71,45 +71,58 @@ class JsonParser(input: ParserInput) { // http://tools.ietf.org/html/rfc4627#section-2.2 private def `object`(): Unit = { ws() - @tailrec def members(map: Map[String, JsValue]): Map[String, JsValue] = { - `string`() - require(':') - ws() - val key = sb.toString - `value`() - val nextMap = map.updated(key, jsValue) - if (ws(',')) members(nextMap) else nextMap + jsValue = if (cursorChar != '}') { + @tailrec def members(map: Map[String, JsValue]): Map[String, JsValue] = { + `string`() + require(':') + ws() + val key = sb.toString + `value`() + val nextMap = map.updated(key, jsValue) + if (ws(',')) members(nextMap) else nextMap + } + var map = Map.empty[String, JsValue] + map = members(map) + require('}') + JsObject(map) + } else { + advance() + JsObject.empty } - var map = Map.empty[String, JsValue] - if (cursorChar != '}') map = members(map) - require('}') ws() - jsValue = JsObject(map) } // http://tools.ietf.org/html/rfc4627#section-2.3 private def `array`(): Unit = { ws() - val list = Vector.newBuilder[JsValue] - @tailrec def values(): Unit = { - `value`() - list += jsValue - if (ws(',')) values() + jsValue = if (cursorChar != ']') { + val list = Vector.newBuilder[JsValue] + @tailrec def values(): Unit = { + `value`() + list += jsValue + if (ws(',')) values() + } + values() + require(']') + JsArray(list.result()) + } else { + advance() + JsArray.empty } - if (cursorChar != ']') values() - require(']') ws() - jsValue = JsArray(list.result()) } // http://tools.ietf.org/html/rfc4627#section-2.4 private def `number`() = { val start = input.cursor + val startChar = cursorChar ch('-') `int`() `frac`() `exp`() - jsValue = JsNumber(input.sliceCharArray(start, input.cursor)) + jsValue = + if (startChar == '0' && input.cursor - start == 1) JsNumber.zero + else JsNumber(input.sliceCharArray(start, input.cursor)) ws() } |