2010-04-29 20 views
5

Tengo una var que tiene unos datos JSON:decodificación JSON con mochijson2 en Erlang

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

Usando mochijson2, que decodificar los datos:

Struct = mochijson2:decode(A). 

Y ahora tengo esto:

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

Estoy tratando de leer (por ejemplo), "trabajo" o "id".

Intenté usar struct.get_value pero parece que no funciona.

¿Alguna idea?

Respuesta

13

Los datos están en {struct, proplist()} formato, por lo que aquí es lo que haces:

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

Puede leer más sobre proplist en: http://www.erlang.org/doc/man/proplists.html

1

Agregando a la respuesta dada anteriormente hay también un buen tutorial en mochiweb, json (video).

2

Aquí hay otro método para acceder a los datos. Utiliza records syntax para facilitar su 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), 

Hace exactamente lo mismo que la respuesta usando registros en su lugar. Otra opción más al usar mochijson2. A mí personalmente me gusta más esta sintaxis.

5

Otra función auxiliar para acceder a la estructura 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. 

Uso:

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 

No creo que la extracción de los valores de JSON puede ser más sencillo.

1

Mi forma favorita de manejar los datos de mochijson es reemplazar todas las estructuras con mapas de hash, después de lo cual se pueden emparejar perfectamente. Para ello he escrito este fácil de entender la función:

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. 

Aquí está un ejemplo de cómo se usa:

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

Esto tiene muchas ventajas, especialmente cuando se trabaja con datos de entrada que puede tener un inesperado forma.

Cuestiones relacionadas