Decodifica JSON con mochijson2 en Erlang
mochiweb (5)
Tengo una var que tiene algunos datos JSON:
A = <<"{/"job/": {/"id/": /"1/"}}">>.
Usando mochijson2, decodifico 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.
¿Algunas ideas?
Los datos están en formato {struct, proplist ()}, así que esto es lo que debes hacer:
{struct, JsonData} = Struct,
{struct, Job} = proplists:get_value(<<"job">>, JsonData),
Id = proplists:get_value(<<"id">>, Job),
Puede leer más sobre los candidatos en: http://www.erlang.org/doc/man/proplists.html
Además de la respuesta anterior, también hay un buen tutorial en mochiweb, json (video).
Aquí hay otro método para acceder a los datos. Utiliza la sintaxis de los registros 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.
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 extraer valores de json sea más simple.
Mi forma favorita de manejar los datos de mochijson es reemplazar todas las estructuras con mapas de hash, después de lo cual pueden ser perfectamente combinados. Para hacerlo, escribí esta función fácil de entender:
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í hay un ejemplo de cómo usarlo:
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 entrantes que pueden tener una forma inesperada.