Help with Scala parsing classes and JSON

616 views
Skip to first unread message

Sean Rhea

unread,
Nov 4, 2012, 5:05:27 PM11/4/12
to scala...@googlegroups.com
scala.util.parsing.json.JSON isn't thread safe, according to the following link:


In a comment in that same thread, Jason Zaugg suggests instead creating a separate scala.util.parsing.json.Parser for each thread and using that. Can anyone reply with a code example that implements that suggestion? I can't figure out how to knit all of the required pieces together. (Perhaps I'm missing some subtle difference between StdTokenParsers and StandardTokenParsers?)

Thanks,
Sean
-- 
I lived for a time in New York City. Just a little bit north of that urban prison, I knew of a beautiful flat spot among the trees, just big enough for me to lie down. It was easy to get to from the confines of my apartment, and I slept there often, alone under the stars. It can be done. --Mike Clelland

Matthew Neeley

unread,
Nov 4, 2012, 5:43:36 PM11/4/12
to scala...@googlegroups.com
You could do something like this:

import scala.util.parsing.json._

// copied implementation of JSON object from standard lib, but make it a class
class SafeJSON extends Parser {

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
}

def parseRaw(input : String) : Option[JSONType] =
phrase(root)(new lexical.Scanner(input)) match {
case Success(result, _) => Some(result)
case _ => None
}

def parseFull(input: String): Option[Any] =
parseRaw(input) match {
case Some(data) => Some(resolveType(data))
case None => None
}

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
}

def perThreadNumberParser_=(f : NumericParser) { numberParser.set(f) }
def perThreadNumberParser : NumericParser = numberParser.get()
}

// SafeJSON behaves like JSON from standard lib, but stores per-thread
parser instances
// in a thread-local variable and then delegates method calls to the
appropriate parser instance.
object SafeJSON {
private parser = new ThreadLocal[SafeJSON] {
override def initialValue = new SafeJSON
}

def parseRaw(input: String): Option[JSONType] = parser.get.parseRaw(input)
def parseFull(input: String): Option[Any] = parser.get.parseFull(input)

def resolveType(input: Any): Any = parser.get.resolveType(input)

// additional methods can be similarly proxied here...
}

--Matthew
> --
> You received this message because you are subscribed to the Google Groups
> "Bay Area Scala Enthusiasts" group.
> To post to this group, send email to scala...@googlegroups.com.
> To unsubscribe from this group, send email to
> scala-base+...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/scala-base?hl=en.

Sean Rhea

unread,
Nov 4, 2012, 7:58:55 PM11/4/12
to scala...@googlegroups.com
That's perfect. Thanks, Matthew!

Sean
Reply all
Reply to author
Forward
0 new messages