简体   繁体   中英

Idiomatically accessing json objects with clojurescript

Anyone have any docs for idiomatic clojurescript for access a javascript object (returned as json, essentially a hash)?

I have a JSON object returned via an AJAX request:

{
  list: [1,2,3,4,5],
  blah: "vtha",
  o: { answer: 42 }
}

How do I access these fields using clojurescript?

I can do:

(.-list data)

But how does this work when I have nested values and objects?

(.-answer (.-o data))

The above seems to be quite clumsy, especially given the nice js syntax of: data.o.answer.

What is the idiomatic way of accessing json objects with clojurescript?

Note:

I realised that I can actually refer to elements using JS syntax, which is quite handy actually. So the following will work correctly:

(str data.o.answer)

You probably want aget:

(aget foo "list")

aget isn't variadic yet, but hopefully will be soon it's variadic now. (aget data "o" "answer") would work

Firstly, your proposed syntax for nested access does work:

ClojureScript:cljs.user> (def data 
    (JSON/parse "{\"list\": \"[1,2,3,4,5]\", \"blah\": \"vtha\", \"o\": {\"answer\": \"42\"}}"))
#<[object Object]>
ClojureScript:cljs.user> (.-answer (.-o data))
"42"

You can use the threading macros...

ClojureScript:cljs.user> (-> data (.-o) (.-answer))
"42"

Or .. notation

ClojureScript:cljs.user> (.. data -o -answer)
"42"

If you're dealing with any amount of data, I'd convert the JSON into clojure data structures and then use the usual idioms:

(let [my-json (js* "{
                     list: [1,2,3,4,5],
                     blah: \"vtha\",
                     o: { answer: 42 }
                   }")
      converted (js->clj my-json)]

  (get-in converted ["list" 3]) ;; => 4
  (-> converted "o" "answer") ;;=> 42
)

(Note: don't use js* if you can help it; it's not idiomatic and might go away in future versions of ClojureScript.)

Clojurescript has a .. operator that is useful for chained javascript calls:

(.. data -o -answer) => data.o.answer => 42
(aget (.. data -list) 1) => data.list[1] => 2

You can use most list operators on arrays too, eg

(into [] (.. data -list)) ; vector [1 2 3 4]

Forget about aget, it's mainly designed for array (array get). Use

  • goog.object/get
  • goog.object/set

See more

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM