2010-04-29 8 views
5

Ho un var che ha alcuni dati JSON:Decode JSON con mochijson2 in Erlang

A = <<"{\"job\": {\"id\": \"1\"}}">>. 

Utilizzando mochijson2, ho decodificare i dati:

Struct = mochijson2:decode(A). 

E ora ho questo:

{struct,[{<<"job">>,{struct,[{<<"id">>,<<"1">>}]}}]} 

Sto cercando di leggere (ad esempio), "lavoro" o "id".

Ho provato a utilizzare struct.get_value ma non sembra funzionare.

Qualche idea?

risposta

13

I dati sono in {, struct proplist()} formato, ecco cosa dovete fare:

{struct, JsonData} = Struct, 
{struct, Job} = proplists:get_value(<<"job">>, JsonData), 
Id = proplists:get_value(<<"id">>, Job), 

Si può leggere di più su proplists a: http://www.erlang.org/doc/man/proplists.html

1

aggiunta alla risposta data in precedenza non c'è anche un bel tutorial su mochiweb, json (video).

2

Ecco un altro metodo di accesso ai dati. Utilizza records syntax per facilità d'uso.

-record(struct, {lst=[]}). 

A = <<"{\"job\": {\"id\": \"1\"}}">>, 
Struct = mochijson2:decode(A), 
Job = proplists:get_value(<<"job">>, Struct#struct.lst), 
Id = proplists:get_value(<<"id">>, Job#struct.lst), 

Fa esattamente la stessa cosa della risposta utilizzando i record. Solo un'altra opzione quando si utilizza mochijson2. A me personalmente piace questa sintassi.

5

Un'altra funzione di supporto per accedere struttura JSON:

jsonobj({struct,List}) -> 
    fun({contains,Key}) -> 
     lists:keymember(Key,1,List); 
    ({raw,Key}) -> 
     {_,Ret} = lists:keyfind(Key,1,List),Ret; 
    (Key) -> 
     {_,Ret} = lists:keyfind(Key,1,List), 
     jsonobj(Ret) 
    end; 
jsonobj(List) when is_list(List) -> 
    fun(len) -> 
     length(List); 
    (Index) -> 
     jsonobj(lists:nth(Index,List)) 
    end; 
jsonobj(Obj) -> Obj. 

Usage:

1> A=mochijson2:decode(<<"{\"job\": {\"id\": \"1\", \"ids\": [4,5,6], \"isok\": true}}">>). 
2> B=jsonobj(A). 
3> B(<<"job">>). 
#Fun<jsonutils.1.33002110> 
4> (B(<<"job">>))(<<"id">>). 
1 
5> (B(<<"job">>))(<<"ids">>). 
#Fun<jsonutils.1.9495087> 
6> (B(<<"job">>))({raw,<<"ids">>}). 
[4,5,6] 
7> ((B(<<"job">>))(<<"ids">>))(1). 
4 
8> B({raw,<<"job">>}). 
{struct,[{<<"id">>,<<"1">>}, 
       {<<"ids">>,[1,2,3]}, 
       {<<"isok">>,true}]} 
9> B({contains,<<"job">>}). 
true 
10> B({contains,<<"something">>}). 
false 
11> ((B(<<"job">>))(<<"ids">>))(len) 
3 

Non credo che l'estrazione di valori da JSON può essere più semplice.

1

Il mio modo preferito di gestire i dati di mochijson sta sostituendo tutte le strutture con le mappe hash dopo le quali possono essere perfettamente abbinate. Per farlo ho scritto questo facile da capire la funzione:

structs_to_maps({struct, Props}) when is_list(Props) -> 
    lists:foldl(
     fun({Key, Val}, Map) -> 
      Map#{Key => structs_to_maps(Val)} 
     end, 
     #{}, 
     Props 
    ); 
structs_to_maps(Vals) when is_list(Vals) -> 
    lists:map(
     fun(Val) -> 
      structs_to_maps(Val) 
     end, 
     Vals 
    ); 
structs_to_maps(Val) -> 
    Val. 

Ecco un esempio di come usarlo:

do() -> 
    A = <<"{\"job\": {\"id\": \"1\"}}">>, 
    Data = structs_to_maps(mochijson2:decode(A)), 
    #{<<"job">> := #{<<"id">> := Id}} = Data, 
    Id. 

Questo ha molti vantaggi soprattutto quando si lavora con i dati in entrata che può avere un inatteso forma.