FCM设备组BadJsonFormat - 正确形成json

时间:2017-03-10 16:32:51

标签: json http erlang firebase-cloud-messaging

我被fcm的原始json体淹没了:

 Body = mochijson2:encode([ {<<"operation">>, <<"create">>},{<<"notification_key_name">>, <<"console group">>},{<<"registration_ids">>, [<<"02aa6XXXX3c9b6d">>,<<"APA91bGtaXXXXXXXXXXXXoi4UH8vIdZk1X67A_9izpSFSHV3BXxdIwG">>]}]).

根据documentation发送POST请求以创建群组:

httpc:request(post, {Url, [{"Authorization", KeyApi}, {"project_id", ProjectId}], "application/json", Body},[{timeout, 5000}], []).

但我收到错误BadJsonFormat:

{ok,{{"HTTP/1.1",400,"Bad Request"},
     [{"cache-control","private, max-age=0"},
      {"date","Fri, 10 Mar 2017 16:19:37 GMT"},
      {"accept-ranges","none"},
      {"server","GSE"},
      {"vary","Accept-Encoding"},
      {"content-length","25"},
      {"content-type","application/json; charset=UTF-8"},
      {"expires","Fri, 10 Mar 2017 16:19:37 GMT"},
      {"x-content-type-options","nosniff"},
      {"x-frame-options","SAMEORIGIN"},
      {"x-xss-protection","1; mode=block"},
      {"alt-svc","quic=\":443\"; ma=2592000; v=\"36,35,34\""}],
     "{\"error\":\"BadJsonFormat\"}"}}

但是mochijson2:decode(Body)工作正常,它看起来像是正确形成的json,但无论如何我都得到错误BadJsonFormat。

出了什么问题?我该如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

函数mochijson2:encode不返回字符串或二进制文件,而是返回一个iolist:

1>  Body = mochijson2:encode([ {<<"operation">>, <<"create">>},{<<"notification_key_name">>, <<"console group">>},{<<"registration_ids">>, [<<"02aa6XXXX3c9b6d">>,<<"APA91bGtaXXXXXXXXXXXXoi4UH8vIdZk1X67A_9izpSFSHV3BXxdIwG">>]}]).
[123,
 [34,<<"operation">>,34],
 58,
 [34,<<"create">>,34],
 44,
 [34,<<"notification_key_name">>,34],
 58,
 [34,<<"console group">>,34],
 44,
 [34,<<"registration_ids">>,34],
 58,
 [91,
  [34,<<"02aa6XXXX3c9b6d">>,34],
  44,
  [34,<<"APA91bGtaXXXXXXXXXXXXoi4UH8vIdZk1X67A_9izpSF"...>>,
   34],
  93],
 125]

这本身没有任何问题。使用iolists而不是字符串或二进制文件意味着您不必创建昂贵的平面数据结构,只需将其写入文件或套接字,然后将其丢弃即可。像file:write_filegen_tcp:send这样的函数处理iolists以及字符串或二进制文件。

但是,httpc:request没有!

让我们通过在shell中使用netcat在端口1111上启动服务器来测试:

$ nc -l 1111

然后从Erlang shell发出请求:

3> httpc:request(post, {"http://127.0.0.1:1111", [], "application/json", Body},[{timeout, 5000}], []).

netcat服务器显示此输出:

POST / HTTP/1.1
content-type: application/json
content-length: 13
te:
host: 127.0.0.1:1111
connection: keep-alive

{"operation":"create",....

请注意content-length是13而不是159! httpc:request能够发送iolist,但它使用函数length而不是iolist_size生成content-length标头,因此服务器只考虑前13个JSON对象的字节,它本身不是有效的JSON。

解决方案是将iolist_to_binary(Body)传递给httpc:request,而不只是Body