From f1c6333e75cbd4eb594e4fad2b023c8259eb260f Mon Sep 17 00:00:00 2001 From: Antonio Cunei Date: Fri, 4 Jun 2010 23:46:31 +0000 Subject: Merged revisions 22170 via svnmerge from https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r22170 | dchenbecker | 2010-06-05 01:05:57 +0200 (Sat, 05 Jun 2010) | 7 lines Fix for #3284. This code should probably be refactored, but in the interest of not breaking backwards compatibility, the JSON.parse method has been marked deprecated for now. Unit tests have been fixed so that this won't break the build this time. ........ --- src/library/scala/util/parsing/json/JSON.scala | 52 +++++++++++++++--------- src/library/scala/util/parsing/json/Parser.scala | 29 ++++++++++++- 2 files changed, 60 insertions(+), 21 deletions(-) (limited to 'src/library') diff --git a/src/library/scala/util/parsing/json/JSON.scala b/src/library/scala/util/parsing/json/JSON.scala index 1be8a10931..6d3761af52 100644 --- a/src/library/scala/util/parsing/json/JSON.scala +++ b/src/library/scala/util/parsing/json/JSON.scala @@ -41,8 +41,33 @@ object JSON extends Parser { * * @param input the given JSON string. * @return an optional list of of elements. + * + * @deprecated Use parseFull or parseRaw as needed. + */ + def parse(input: String): Option[List[Any]] = parseRaw(input).map(unRaw).flatMap({ + case l : List[_] => Some(l) + case _ => None + }) + + /** + * This method converts "raw" results back into the original, deprecated + * form. */ - def parse(input: String): Option[List[Any]] = + private def unRaw (in : Any) : Any = in match { + case JSONObject(obj) => obj.map({ case (k,v) => (k,unRaw(v))}).toList + case JSONArray(list) => list.map(unRaw) + case x => x + } + + /** + * Parse the given JSON string and return a list of elements. If the + * string is a JSON object it will be a JSONObject. If it's a JSON + * array it will be be a JSONArray. + * + * @param input the given JSON string. + * @return an optional JSONType element. + */ + def parseRaw(input : String) : Option[JSONType] = phrase(root)(new lexical.Scanner(input)) match { case Success(result, _) => Some(result) case _ => None @@ -57,7 +82,7 @@ object JSON extends Parser { * @return an optional list or map. */ def parseFull(input: String): Option[Any] = - parse(input) match { + parseRaw(input) match { case Some(data) => Some(resolveType(data)) case None => None } @@ -66,23 +91,12 @@ object JSON extends Parser { * A utility method to resolve a parsed JSON list into objects or * arrays. See the parse method for details. */ - def resolveType(input: List[_]): Any = { - var objMap = Map[String, Any]() - - if (input.forall { - case (key: String, value: List[_]) => - objMap = objMap.+[Any](key -> resolveType(value)) - true - case (key : String, value) => - objMap += key -> value - true - case _ => false - }) objMap - else - input.map { - case l : List[_] => resolveType(l) - case x => x - } + def resolveType(input: Any): Any = input match { + case JSONObject(data) => data.transform { + case (k,v) => resolveType(v) + } + case JSONArray(data) => data.map(resolveType) + case x => x } /** diff --git a/src/library/scala/util/parsing/json/Parser.scala b/src/library/scala/util/parsing/json/Parser.scala index 0d573edce4..e8e7897ca4 100644 --- a/src/library/scala/util/parsing/json/Parser.scala +++ b/src/library/scala/util/parsing/json/Parser.scala @@ -15,6 +15,31 @@ import scala.util.parsing.combinator.syntactical._ import scala.util.parsing.combinator.lexical._ /** + * A marker class for the JSON result types. + * + * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> + */ +sealed abstract class JSONType + +/** + * Represents a JSON Object (map). + * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> + */ +case class JSONObject (obj : Map[Any,Any]) extends JSONType { + override def toString = "JSONObject(" + obj.map({ case (k,v) => k + " -> " + v }).mkString(", ") + ")" +} + +/** + * Represents a JSON Array (list). + * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> + */ +case class JSONArray (list : List[Any]) extends JSONType { + override def toString = "JSONArray(" + list.mkString(", ") + ")" +} + +/** + * The main JSON Parser. + * * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> */ class Parser extends StdTokenParsers with ImplicitConversions { @@ -39,8 +64,8 @@ class Parser extends StdTokenParsers with ImplicitConversions { // Define the grammar def root = jsonObj | jsonArray - def jsonObj = "{" ~> repsep(objEntry, ",") <~ "}" - def jsonArray = "[" ~> repsep(value, ",") <~ "]" + def jsonObj = "{" ~> repsep(objEntry, ",") <~ "}" ^^ { case vals : List[_] => JSONObject(Map(vals : _*)) } + def jsonArray = "[" ~> repsep(value, ",") <~ "]" ^^ { case vals : List[_] => JSONArray(vals) } def objEntry = stringVal ~ (":" ~> value) ^^ { case x ~ y => (x, y) } def value: Parser[Any] = (jsonObj | jsonArray | number | "true" ^^^ true | "false" ^^^ false | "null" ^^^ null | stringVal) def stringVal = accept("string", { case lexical.StringLit(n) => n} ) -- cgit v1.2.3