How do I parse JSON via js.Dynamic?

659 views
Skip to first unread message

Dino Fancellu

unread,
Sep 10, 2015, 4:56:38 PM9/10/15
to Scala.js
e.g.


I've got the code to do the Ajax, pull into a json response.

val json = js.JSON.parse(xhr.responseText)

but it's all js.Dynamic, and I don't know how to properly navigate

e.g. I'd like to dig down to the list array and find all the dt and main/temp values

Thanks.

Dino Fancellu

unread,
Sep 10, 2015, 5:00:33 PM9/10/15
to Scala.js

Justin du coeur

unread,
Sep 10, 2015, 5:47:19 PM9/10/15
to Dino Fancellu, Scala.js
You probably need to build a facade -- a JavaScript interface -- for the data, as described here: http://www.scala-js.org/doc/calling-javascript.html

Basically, you define a collection of Scala traits, descending from js.Object, that describe the data in a strongly-typed way.

--
You received this message because you are subscribed to the Google Groups "Scala.js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-js+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scala-js/4e7488a6-9f42-429e-97cc-ef950c353f2a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Dino Fancellu

unread,
Sep 10, 2015, 6:53:32 PM9/10/15
to Scala.js, dino.f...@gmail.com
That really doesn't tell me anything. That's just saying "you need to write some s/w"

I was looking for a specific answer to something that must have been done before in the scala.js world.


No need to create bindings here. 

However the there is no dealing with arrays in this example code.

Dino.

Dino Fancellu

unread,
Sep 10, 2015, 7:18:22 PM9/10/15
to Scala.js, dino.f...@gmail.com
Ok, found a way forward, a bit. 

An old posting asking the same question.


e.g.

val list=json.list.asInstanceOf[js.Array[js.Dynamic]]             
              list.foreach{
               el=>println(el.dt)
            }

Also looks like I can get the array values like this

 // will return 0th index, i.e. 1st.
 // a bit surprising considering you pass in a string

json.list.selectDynamic("0").dt

you can also get the size of the array similarly

json.list.selectDynamic("length")

and use that to index into the array

Dino

Erik LaBianca

unread,
Sep 10, 2015, 7:25:30 PM9/10/15
to Dino Fancellu, Scala.js
You have two options. 

The first, as per the example you linked, is simply using js.Dynamic. The docs for it are at http://www.scala-js.org/doc/calling-javascript.html, and you basically write scala code as if it were javascript. You won’t get introspection support from the IDE, because it’s dynamic. You can still poke around in your browser to figure out what the calls are. You probably just want something like json.list(0).main.temp to refer to the temperature of the first element.

The more “idiomatic” way to do this, however, is what Justin suggested. You build a “facade” around the data, describing the elements that you expect in the json. Then, you simply cast the parsed json to the facade and use it as native scala.

Probably something like this:

trait Weather extends js.Object  {
weather: WeatherMessage = js.native
}

trait WeatherMessage extends js.Object {
list: js.Array[WeatherReport] = js.native
}

trait Weather extends js.Object {
main: WeatherMain = js.native
}

trait WeatherMain extends js.Object {
temp: Float = js.native
}

As you can see, you’ll have to describe the entire schema. But if you do it, correctly, you’ll have full type checking of all your code and IDE support for introspection.

—erik


Dino Fancellu

unread,
Sep 10, 2015, 8:29:43 PM9/10/15
to Scala.js, dino.f...@gmail.com
Just found I can say 

json.list.length to get the length of the list

json.list(0) unfortunately doesn't work

I get an error saying "json.list is not a function"

Anyway, I have a way forward with js.Array[js.Dynamic) coercion, or list.selectDynamic("idx")

Can't be bothered with building static bindings as its just some demo code. Was simply bewildered about how hard it is to parse out of the box.
I'll probably pimp it to have a nice int idx apply(). Amazed it doesn't have one as standard.

Dino.

Haoyi Li

unread,
Sep 10, 2015, 8:32:03 PM9/10/15
to Dino Fancellu, Scala.js
Can't be bothered with building static bindings as its just some demo code. Was simply bewildered about how hard it is to parse out of the box.
I'll probably pimp it to have a nice int idx apply(). Amazed it doesn't have one as standard.


Unfortunately, nobody has stepped up to make it happen. Could that person be you? =D

Dino Fancellu

unread,
Sep 10, 2015, 8:40:21 PM9/10/15
to Scala.js, dino.f...@gmail.com
Well, I've only been using scala.js for a few days.

Will have to see what else comes up in my life. Just surprised that with so many people using scala.js the JSON side is so basic.

Currently working on some Ractive.js bindings, which I want to get done and put in a proper project.

i.e.


BTW have read your scala.js hands on. Very very good. I took your Ajax weather call and made it use Ractive for my demo code.

Dino.

Sébastien Doeraene

unread,
Sep 11, 2015, 12:50:19 AM9/11/15
to Dino Fancellu, Scala.js

Hi,

Most Scala.js folks don't directly manipulate json. We have automated serializers instead, which explains why nobody cares about a better json manipulation api.

js.Dynamic itself *does* have an `apply` method, but it's for calling a function, not indexing an array. This is one unfortunate piece of syntax where Scala conflates into 1 syntax something with 2 different syntaxes in js. We can only support 1 of them by default in js.Dynamic.

Cheers,
Sébastien

Dino Fancellu

unread,
Sep 11, 2015, 5:48:51 AM9/11/15
to Scala.js, dino.f...@gmail.com
When you talk about "automated serializers", do you have an example of that?

Thanks.

Dino.

chandra sekhar kode

unread,
Sep 11, 2015, 7:24:13 AM9/11/15
to Scala.js, dino.f...@gmail.com

Justin du coeur

unread,
Sep 11, 2015, 8:14:29 AM9/11/15
to Dino Fancellu, Scala.js
On Thu, Sep 10, 2015 at 8:29 PM, Dino Fancellu <dino.f...@gmail.com> wrote:
Can't be bothered with building static bindings as its just some demo code. Was simply bewildered about how hard it is to parse out of the box.
I'll probably pimp it to have a nice int idx apply(). Amazed it doesn't have one as standard.

To some degree it's a cultural thing.  Keep in mind that the main reason to use Scala.js is strong typing -- while Scala has many advantages over JavaScript, that's by far the biggest and most important.  So my attitude is that, if it's worth having in my code, it's worth putting a strongly-typed facade around, so that I have some confidence in it, and can maintain it safely.

It's true that if you're just doing something slash-and-burn that isn't as necessary, but it typically only takes me a minute or two to add a simple facade (it's much, much easier than people tend to expect), and then I have a much easier-to-understand record of what I think the data structure looks like...
Reply all
Reply to author
Forward
0 new messages