2012-03-22 3 views
15

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

У меня есть объект 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

Я предполагаю, что в вашей фактической установки, вы получите надлежащее JSON? –

+0

Да, фактический JSON –

+0

До сих пор я думаю, что ответ действительно: нет идиоматического способа сделать это (пока). –

ответ

10

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

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" 
+0

Действительно работает, по-прежнему кажется неуклюжим для меня, даже с помощью макросов. –

+1

parens in threading являются избыточными '(-> data.-O.-Answer)' – noisesmith

+1

@noisesmith в эти дни я бы предпочел использовать '' (.. data -o -answer) '', как отмечено @ stephen-nelson - я обновлю ответ – sw1nn

5

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

+0

Я нахожу, что данные преобразуются в вектор, а не в хэш, поэтому на самом деле больше co, plicated для извлечения данных, чем объект js по умолчанию –

+0

Фактически, преобразованные данные кажутся меняться непредсказуемо ... obj map или vector –

+0

Это похоже на покупку всего продуктового магазина, чтобы получить апельсины. Пустая трата ресурсов. –

16

Вы, вероятно, хотите AGET:.

(aget foo "list") 

AGET не VARIADIC пока нет, но, надеюсь, скоро будет теперь это VARIADIC. (aget data "o" "answer") будет работать

+3

Для справки, теперь это переменный. (данные aget «o» «ответ») будут работать. –

+0

FWIW, Дэвид отменил бы этот ответ в наши дни, и вместо этого предложит вместо этого '(goog.object/get foo" list ")'. См. Больше в ответе Jiacai Liu. –

1

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] 
Смежные вопросы