我是Erlang
的新手,并注意到没有本机函数从列表创建json字符串(或者是什么?无论如何)我使用此方法在Erlang中创建json字符串但不知道它是否会不故障 ..
这是我的方法的一个例子。
-module(index).
-export([test/0]).
test()->
Ma = "Hello World", Mb = "Hello Erlang",
A = "{\"Messages\" : [\"" ++ Ma ++ "\", \""++Mb++"\"], \"Usernames\" : [\"Username1\", \"Username2\"]}", A.
结果是:
388> test().
"{\"Messages\" : [\"Hello World\", \"Hello Erlang\"], \"Usernames\" : [\"Username1\", \"Username2\"]}"
389>
我认为这是预期的结果,但是当包含特殊字符时,此方法可能会出现故障,例如“Quotes,&lt;,&gt;,&amp; / \”? < / p>
我应该采取哪些预防措施来加强这种方法?
答案 0 :(得分:2)
如果Ma
或Mb
包含双引号或任何控制字符,则从字符串到JSON的解析将失败。这种解析可能永远不会出现在Erlang中,因为Erlang没有内置的字符串到JSON转换。
使用二进制文件(<<"I am a binary string">>
)是个好主意,因为列表会占用更多资源。
我们正在使用jiffy,它被实现为NIF因此速度相当快,它允许文档构造如下:
jiffy:decode(<<"{\"foo\": \"bar\"}">>).
{[{<<"foo">>,<<"bar">>}]}
Doc = {[{foo, [<<"bing">>, 2.3, true]}]}.
{[{foo,[<<"bing">>,2.3,true]}]}
jiffy:encode(Doc).
<<"{\"foo\":[\"bing\",2.3,true]}">>
答案 1 :(得分:1)
我遇到了同样的问题,上下搜索,最后想出了自己的方法。这纯粹是为人们指明正确的方向,以为自己找到解决方案。注意:我尝试了jiffy,但是由于我正在使用rebar3,因此目前不兼容。
我正在使用MS sql服务器,所以我使用Erlang odbc模块:http://erlang.org/doc/man/odbc.html
odbc:sql_query / 2给了我<i>
// For each angular application we want to host:
app.Map(new PathString("/home"), home =>
{
if (env.IsDevelopment())
{
StaticFileOptions clienthome = new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @"home"))
};
home.UseSpaStaticFiles(clienthome);
home.UseSpa(spa =>
{
spa.Options.SourcePath = "home"; // spa.Options.StartupTimeout = new TimeSpan(0, 5, 0);
spa.UseAngularCliServer(npmScript: "start"); // it will use package.json & will search for start command to run
});
}
else
{
// Each map gets its own physical path for it to map the static files to.
StaticFileOptions clienthome = new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @"home/dist"))
};
// Each map its own static files otherwise it will only ever serve index.html no matter the filename
home.UseSpaStaticFiles(clienthome);
// Each map will call its own UseSpa where we give its own sourcepath
home.UseSpa(spa =>
{
spa.Options.StartupTimeout = new TimeSpan(0, 1, 30);
spa.Options.SourcePath = "home";
spa.Options.DefaultPageStaticFileOptions = clienthome;
});
}
});
</i>
从这里,我可以使用{selected, Columns, Results}
,它是字符串和结果的列表,行的列表分别表示为元组,然后创建一些函数以输出有效的Erlang代码,从而能够正确地序列化到基于Json的代码在许多因素上。这是完整的代码:
进行初始查询:
Columns
然后输入函数是 Sql = "SELECT * FROM alloys;",
Ref = connect(),
case odbc:sql_query(Ref, Sql) of
{selected, Columns, Results} ->
set_json_from_sql(Columns, Results, []);
{error, Reason} ->
{error, Reason}
end.
,它将调用以下函数:
set_json_from_sql/3
因此format_by_type(Item) ->
if
is_list(Item) -> list_to_binary(io_lib:format("~s", [Item]));
is_integer(Item) -> Item;
is_boolean(Item) -> io_lib:format("~a", [Item]);
is_atom(Item) -> Item
end.
json_by_type([H], [Hc], Data) ->
NewH = format_by_type(H),
set_json_flatten(Data, Hc, NewH);
json_by_type([H|T], [Hc|Tc], Data) ->
NewH = format_by_type(H),
NewData = set_json_flatten(Data, Hc, NewH),
json_by_type(T, Tc, NewData).
set_json_flatten(Data, Column, Row) ->
ResTuple = {list_to_binary(Column), Row},
lists:flatten(Data, [ResTuple]).
set_json_from_sql([], [], Data) -> jsone:encode([{<<"data">>, lists:reverse(Data)}]);
set_json_from_sql(Columns, [H], Data) ->
NewData = set_json_merge(H, Columns, Data),
set_json_from_sql([], [], NewData);
set_json_from_sql(Columns, [H|T], Data) ->
NewData = set_json_merge(H, Columns, Data),
set_json_from_sql(Columns, T, NewData).
set_json_merge(Row, Columns, Data) ->
TupleRow = json_by_type(tuple_to_list(Row), Columns, []),
lists:append([TupleRow], Data).
在匹配set_json_from_sql/3
之后会给您Json输出。
这里的关键点是您需要为字符串和原子调用set_json_from_sql([], [], Data)
。使用list_to_binary/1
将Erlang对象编码为Json:https://github.com/sile/jsone
而且,注意jsone
用于匹配Erlang对象类型,是的,不是很理想,但是只要您知道数据库的类型即可工作,或者您可以增加额外的保护措施来适应这种情况。
答案 2 :(得分:0)
这对我有用
test()->
Ma = "Hello World", Mb = "Hello Erlang",
A = "{\"Messages\" : {{\"Ma\":\"" ++ Ma ++ "\"}, {\"Mb\":\""++Mb++"\"}}, {\"Usernames\" : {\"Username1\":\"usrname1\"}, {\"Username2\":\"usrname2\"}}",
io:format("~s~n",[A]).
输出
10> io:format("~s~n",[A]).
{"Messages" : {{"Ma":Hello World"}, {"Mb":Hello Erlang"}}, {"Usernames" : {"Username1":"usrname1"}, {"Username2":"usrname2"}}
ok
或使用github上的许多库之一将erlang术语转换为json。 My Tuple to JSON module is simple but effective.
答案 3 :(得分:-1)
像pro
一样-define(JSON_WRAPPER(Proplist), {Proplist}).
-spec from_list(json_proplist()) -> object().
from_list([]) -> new();
from_list(L) when is_list(L) -> ?JSON_WRAPPER(L).
-spec to_binary(atom() | string() | binary() | integer() | float() | pid() | iolist()) -> binary().
to_binary(X) when is_float(X) -> to_binary(mochinum:digits(X));
to_binary(X) when is_integer(X) -> list_to_binary(integer_to_list(X));
to_binary(X) when is_atom(X) -> list_to_binary(atom_to_list(X));
to_binary(X) when is_list(X) -> iolist_to_binary(X);
to_binary(X) when is_pid(X) -> to_binary(pid_to_list(X));
to_binary(X) when is_binary(X) -> X.
-spec recursive_from_proplist(any()) -> object().
recursive_from_proplist([]) -> new();
recursive_from_proplist(List) when is_list(List) ->
case lists:all(fun is_integer/1, List) of
'true' -> List;
'false' ->
from_list([{to_binary(K) ,recursive_from_proplist(V)}
|| {K,V} <- List
])
end;
recursive_from_proplist(Other) -> Other.