Идиоматический доступ к объектам json с clojurescript

У кого-нибудь есть какие-либо документы для идиоматического clojurescript для доступа к объекту javascript (возвращенный как json, по существу хэш)?

У меня есть объект JSON, возвращаемый через запрос AJAX:

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

Как получить доступ к этим полям с помощью clojurescript?

Я могу сделать:

(.-list data)

Но как это работает, когда у меня есть вложенные значения и объекты?

(.-answer (.-o data))

Вышеприведенное кажется довольно неуклюжим, особенно учитывая хороший синтаксис js: data.o.answer.

Каков идиоматический способ доступа к объектам json с clojurescript?

Примечание:

Я понял, что могу фактически ссылаться на элементы с использованием синтаксиса JS, что на самом деле весьма удобно. Таким образом, следующее будет работать правильно:

(str data.o.answer)

Ответы

Ответ 1

Вероятно, вам нужен aget:

(aget foo "list")

aget еще не изменен, но, надеюсь, скоро будет теперь он изменен. (aget data "o" "answer") будет работать

Ответ 2

Во-первых, ваш предложенный синтаксис для вложенного доступа работает:

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"

Вы можете использовать макросы threading...

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

Или .. нотация

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

Ответ 3

Если вы имеете дело с любым количеством данных, я бы преобразовал 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.)

Ответ 4

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]