使用ClojureScript惯用方式访问JSON对象

18

有没有人有使用惯用的ClojureScript方法访问JavaScript对象(作为JSON返回,本质上是哈希表)的文档?

我通过AJAX请求获得了一个JSON对象:


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

我该如何使用ClojureScript访问这些字段?

我可以这样做:

(.-list data)

但是如果我有嵌套的值和对象,这是如何工作的?

(.-answer (.-o data))

以上方法看起来相当笨拙,特别是给出了这样漂亮的JS语法:data.o.answer。

在ClojureScript中访问JSON对象的惯用方式是什么?

注意:

我意识到实际上可以使用JS语法引用元素,这实际上非常方便。因此,以下内容将正常工作:

(str data.o.answer)

1
我假设在你的实际设置中,你得到了正确的JSON? - Felix Kling
到目前为止,我认为答案真的是:还没有惯用的方法来做到这一点。 - Toby Hede
上次回复已经有一段时间了--(str data.o.answer)是否符合惯用语? - cnp
5个回答

17

你可能想要使用 get:

(aget foo "list")

aget目前还不支持可变参数,但希望以后会实现 现在它已经支持可变参数了。(aget data "o" "answer")将会起作用。


3
记录一下,它现在是可变参数的。使用 (aget data "o" "answer") 就可以了。 - Kris Jenkins
值得一提的是,David现在会撤回这个答案,并建议改用(goog.object/get foo "list")。更多信息请参见Jiacai Liu的答案。 - Mike Fikes

11

首先,您提出的嵌套访问语法确实有效:

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"

你可以使用线程宏...

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

或者..表示法

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

确实可以工作,但即使使用线程宏,对我来说仍然感觉笨拙。 - Toby Hede
1
线程中的括号是多余的 (-> data .-o .-answer) - noisesmith
1
@noisesmith 这些天我更喜欢使用 (.. data -o -answer),正如 @stephen-nelson 所指出的那样 - 我会更新答案。 - sw1nn

6
如果你正在处理任何数量的数据,我建议将JSON转换成Clojure数据结构,然后使用通常的惯用语法。
(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
)

(注:如果可以,请不要使用js*;这并不习惯用语,并且在以后的ClojureScript版本中可能会消失。)

我发现数据被转换成向量而不是散列,所以从中提取数据实际上比默认的JS对象更复杂。 - Toby Hede
实际上,转换后的数据似乎变化不可预测... obj map 或 vector。 - Toby Hede
这就像为了得到橙子而买下整个杂货店一样,是一种资源浪费。 - Nikita Volkov

2

2
Clojurescript有一个“..”运算符,用于链接JavaScript调用:
(.. data -o -answer) => data.o.answer => 42
(aget (.. data -list) 1) => data.list[1] => 2

您也可以将大多数列表操作符用于数组,例如:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接