This page is no longer maintained — Please continue to the home page at www.scala-lang.org

accessing JSON parsed data?

3 replies
bobby prescott
Joined: 2010-06-26,
User offline. Last seen 2 years 18 weeks ago.
I ran the JSON1Test program on the address-book.json file from the staircase book to build the following map.

object test {  def main(args: Array[String]) {    val m = Map("address book" ->             Map("name" -> "John Smith", "address" ->                  Map("street" -> "10 Market Street", "city" -> "San Francisco, CA", "zip" -> 94111.0), "phone numbers" ->                    List("408 338-4238", "408 111-6892")))      }}
when I run  println(m("address book")("address")) I get :
Map(street -> 10 Market Street, city -> San Francisco, CA, zip -> 94111.0)
when I try to compile:  println(m("address book")("address")("street")) I get :
test.scala:7: error: m.apply("address book").apply("address") of type java.lang.Object does not take parameters     println(m("address book")("address")("street"))
I need a way to get all the data back out of map?
Markus Knecht
Joined: 2010-06-24,
User offline. Last seen 2 years 9 weeks ago.
Re: accessing JSON parsed data?
Am 26.06.2010 04:40, schrieb robert prescott:
AANLkTinzArx384sFJMkUTBraqXLSSKorkjjgyxjR2e1i [at] mail [dot] gmail [dot] com" type="cite">I ran the JSON1Test program on the address-book.json file from the staircase book to build the following map.

object test {   def main(args: Array[String]) {     val m = Map("address book" ->              Map("name" -> "John Smith", "address" ->                  Map("street" -> "10 Market Street", "city" -> "San Francisco, CA", "zip" -> 94111.0), "phone numbers" ->                     List("408 338-4238", "408 111-6892")))       } }
when I run  println(m("address book")("address")) I get :
Map(street -> 10 Market Street, city -> San Francisco, CA, zip -> 94111.0)
when I try to compile:  println(m("address book")("address")("street")) I get :
test.scala:7: error: m.apply("address book").apply("address") of type java.lang.Object does not take parameters     println(m("address book")("address")("street"))
The problem is, that all values of a Map must have the same static type. Because you have diffrent types in your Map, the compiler can't garantee, that the "adress" entry is again a map and so can't alow you to use apply(String) on it.
AANLkTinzArx384sFJMkUTBraqXLSSKorkjjgyxjR2e1i [at] mail [dot] gmail [dot] com" type="cite">
I need a way to get all the data back out of map?
I'm writing a api at the moment which is adressing this problem and others of Json stuff (it isn't yet finished), but if this simple problem is the ony thing you have, than the overhead of my api is to big. A solution to this problem would be. the following

implicit def jsonMapAccesor[T](a:Any):Map[String,T] = if(a.isInstanceOf[Map[_,_]]) a.asInstanceOf[[Map[_,T]]] else throw new .....Exception
implicit def jsonListAccesor[T](a:Any):List[T] = if(a.isInstanceOf[List[_]]) a.asInstanceOf[List[T]] else throw new .....Exception

if this conversions are in scope, you should be able to use your structure like you whant it. But be aware, that this solution is very risky, because it can tra to convert every thing to a Map/List and if you make a failure the effect is not visible at Compile time, theit will be an Exception at Runtime.

Another a bit less riky solution would be the following

class JsonAccessor[T](a:Any){
    def -->(s:String) = if(a.isInstanceOf[Map[_,_]]) a.asInstanceOf[[Map[_,T]]](s) else throw new .....Exception
    def -->(i:int) = if(a.isInstanceOf[List[_]]) a.asInstanceOf[List[T]](i) else throw new .....Exception
}
implicit def jsonAccesor[T](a:Any):JsonAccessor[T] = new JsonAccessor(a)

Now you have to trigger the conversion by calling --> so it don't happen by mistacke but you have to wirte
println(m("address book")("address")-->("street")) or println(m("address book")-->("address")-->("street"))
Matthew Pocock
Joined: 2010-02-04,
User offline. Last seen 42 years 45 weeks ago.
Re: accessing JSON parsed data?
Hi,

Wouldn't it be better to make --> run in a monad (e.g. Option/List) and change your casting code to return None/Nill if the cast fails?

Matthew

Markus Knecht
Joined: 2010-06-24,
User offline. Last seen 2 years 9 weeks ago.
Re: accessing JSON parsed data?
Am 28.06.2010 15:38, schrieb Matthew Pocock:
AANLkTikvCyFtJR60CJ2uIUJbSceWMfG7u6RtRFOIzX94 [at] mail [dot] gmail [dot] com" type="cite">Hi,

Wouldn't it be better to make --> run in a monad (e.g. Option/List) and change your casting code to return None/Nill if the cast fails?

Matthew

Hello
Yes this is true, but the solution i mailed was for the problem of robert prescott and if we use monads he have to use a get or head or something else to retrive the underlying value, and if it should be save he also has to check before using this methode, to make sure that its not the Nil/None instance of the Monad.
So he would not be able to write something like println(m("address book")-->("address")-->("street")) unless we make an other implicit conversion from the Monad to a class with -->, but even then we had to call an other methode at the end println(m("address book")-->("address")-->("street").getOrElse("")) for example.
I tried to give a fast Simple solution.
The Api which i designe has its own Monad Like Implementation for this, but it would be to Complex to mail this as a Solution for robert prescott's problem

Markus

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland