Quiero crear una lista de tuplas en formato json con jsx: encode, que devuelve el error:

    io:format("Mylist After reverse ==========: ~n~p~n",[Mylist]),

    FinalReading = lists:map(
                fun(X) ->
                    jsx:encode([X])
                end, Mylist),

Mylist se imprime de la siguiente manera:

    [{{<<"name">>,<<"Batman">>},{<<"steps">>,1033},{<<"distance">>,830}},
     {{<<"name">>,<<"Superman">>},{<<"steps">>,641},{<<"distance">>,520}}]

Estoy recibiendo este error:

    09:49:24.048 [error] ** Boss Service Handler myproj_priv_mylib_websocket terminating in handle_incoming/4
    for the reason error:badarg
    ServiceUrl: "/websocket/mylib"
    WebSocketId: <0.336.0>
    SessionId  : <<"a4f60118091309990af7c89c9a1acb49ee3bb08d">>
    Message    : <<"admin@mydomain.com:z3CMLU9jDTYdiAacNiJrMIkdp4lTf6sb">>
    State    : []
    ** Stacktrace: [{jsx_parser,value,4,[{file,"src/jsx_parser.erl"},{line,125}]},{lists,map,2,[{file,"lists.erl"},{line,1237}]},{myproj_priv_mylib_websocket,handle_incoming,5,[{file,"..."},{line,130}]},{boss_service_worker,handle_cast,2,[{file,"src/boss/boss_service_worker.erl"},{line,173}]},{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,599}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]

Sería genial si alguien indicara el código correcto. Agradeciendo a todos de antemano.

2
raich 20 jul. 2016 a las 20:28

2 respuestas

La mejor respuesta

Tendrá que convertir las tuplas de nivel superior en listas usando erlang:tuple_to_list/1 y lists:map/2 para que jsx pueda codificarlas correctamente en una matriz JSON.

1> List = [{{<<"name">>,<<"Batman">>},{<<"steps">>,1033},{<<"distance">>,830}},
1>         {{<<"name">>,<<"Superman">>},{<<"steps">>,641},{<<"distance">>,520}}].
[{{<<"name">>,<<"Batman">>},
  {<<"steps">>,1033},
  {<<"distance">>,830}},
 {{<<"name">>,<<"Superman">>},
  {<<"steps">>,641},
  {<<"distance">>,520}}]
2> List2 = lists:map(fun erlang:tuple_to_list/1, List).
[[{<<"name">>,<<"Batman">>},
  {<<"steps">>,1033},
  {<<"distance">>,830}],
 [{<<"name">>,<<"Superman">>},
  {<<"steps">>,641},
  {<<"distance">>,520}]]
3> io:format("~s~n", [jsx:encode(List2)]).
[{"name":"Batman","steps":1033,"distance":830},{"name":"Superman","steps":641,"distance":520}]
4
Dogbert 20 jul. 2016 a las 17:40

Soy bastante novato en Erlang, así que no estoy seguro de tener derecho a juzgar, pero mi sensación es que sería bueno ocultar la necesidad de convertir la tupla en lista en jsx: encode.

Si

[{a,<<"a">>}, {b,<<"b">>}].

Se convierte

{
  "a" : "a",
  "b" : "b"
}

Creo que lo mismo debería funcionar también para esta sintaxis

{{a,<<"a">>}, {b,<<"b">>}}.

Esta última sintaxis trae más información (refleja un orden con el que puedo contar, dentro del código, para la coincidencia de patrones).

Por lo general, trato de convertir mi JSON en una tupla para la que conozco el orden, para poder jugar con la coincidencia de patrones en lugar de usar keyfind y amigos. Pero debido a que la sintaxis anterior no funciona, tengo que ajustar jsx:encode(tuple_to_list()) para administrar automáticamente "PropTuples".

¿Lo estoy entendiendo completamente mal? ¿Hay una forma más decente de representar / tratar / manipular JSON en Erlang?

1
Riccardo Manfrin 10 nov. 2017 a las 16:48