Идиоматический доступ к объектам json с помощью clojurescript - PullRequest
15 голосов
/ 22 марта 2012

У кого-нибудь есть документы для идиоматического 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)

Ответы [ 5 ]

16 голосов
/ 22 марта 2012

Возможно, вам нужен aget:

(aget foo "list")

aget еще не является вариадическим, но, надеюсь, скоро будет теперь он вариативный.(aget data "o" "answer") будет работать

10 голосов
/ 22 марта 2012

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

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"
5 голосов
/ 22 марта 2012

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

1 голос
/ 29 января 2018

Забудьте о aget, он в основном предназначен для массива (array get). Используйте

  • goog.object / получить
  • goog.object / комплект

Подробнее

1 голос
/ 27 апреля 2013

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]
...