2012-03-22 30 views
15

Cualquier persona tiene documentos para clojurescript idiomático para acceder a un objeto javascript (devuelto como json, esencialmente un hash)?Acceso idiomático a objetos json con clojurescript

Tengo un objeto JSON devuelto a través de una petición AJAX:

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

¿Cómo accedo a estos campos utilizando clojurescript?

que puedo hacer:

(.-list data) 

Pero, ¿cómo funciona esto cuando he anidado valores y objetos?

(.-answer (.-o data)) 

Lo anterior parece ser bastante torpe, especialmente dada la buena sintaxis de JS: data.o.answer.

¿Cuál es la forma idiomática de acceder a los objetos json con clojurescript?

Nota:

me di cuenta de que realmente puedo hacer referencia a elementos usando la sintaxis de JS, que queda muy cerca en realidad. Así que la siguiente funcionará correctamente:

(str data.o.answer) 
+1

Asumo en su configuración actual, se obtiene adecuado JSON? –

+0

Sí, JSON real –

+0

Hasta ahora creo que la respuesta es realmente: no hay una forma idiomática de hacer esto (todavía). –

Respuesta

10

En primer lugar, la sintaxis propuesta para el acceso anidado funciona:

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" 

Usted puede utilizar las macros de roscado ...

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

O .. Notación

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

Realmente funciona, todavía me parece torpe, incluso con el enhebrado de macros. –

+1

los parens en el subprocesamiento son redundantes '(-> data.-O.-Answer)' – noisesmith

+1

@noisesmith en estos días preferiría usar '' (.. data -o -answer) '', como lo señaló @ stephen-nelson - actualizaré la respuesta – sw1nn

5

Si usted está tratando con cualquier cantidad de datos, me convierto el JSON en estructuras de datos clojure y luego usar las expresiones habituales:

(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 
) 

(Nota: no utilice js* si puede evitarlo; no es idiomática y podría desaparecer en futuras versiones de ClojureScript)

+0

Estoy descubriendo que los datos se convierten en un vector en lugar de un hash, por lo que en realidad es más complicado duplicar los datos que el objeto predeterminado js –

+0

En realidad, los datos convertidos parecen para variar impredeciblemente ... obj map or vector –

+0

Esto es como comprar toda la tienda de abarrotes solo para obtener las naranjas. Una pérdida de recursos. –

16

Es posible que desee aget:.

(aget foo "list") 

aget no es variadic todavía, pero espero que sea pronto es variadic ahora. (aget data "o" "answer") funcionaría

+3

Para el registro, es variadic ahora. (datos de edad "o" "respuesta") funcionarían. –

+0

FWIW, David se retractaría de esta respuesta en estos días, y sugeriría en su lugar '(goog.object/get foo" list ")'. Ver más en la respuesta de Jiacai Liu. –

1

Clojurescript tiene una .. operador que es útil el programa JavaScript encadenado llama:

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

Usted puede utilizar la mayoría de los operadores de la lista de matrices también, por ejemplo,

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