我正在使用Poison将地图编码为JSON,并将其发送到Slack API。这就是Poison给我的东西:
"{\"text\":\"changed readme fad996e98e04fd4a861840d92bdcbbcb1e1ec296\"}"
当我把它放入JSON lint时,它说它是有效的JSON,但是Slack响应“无效的有效载荷”。
如果我将JSON更改为这样
{"text":"changed readme fad996e98e04fd4a861840d92bdcbbcb1e1ec296"}
然后它有效。有谁知道我在哪里出错?我是否需要对编码的JSON进行额外处理,或者是否需要设置一些标头?
这是我的控制器
def create(conn, opts) do
message = Message.create_struct(opts)
response = Slack.Messages.send(message)
case response do
{:ok, data} ->
render conn, json: Poison.encode!(data)
{:error, reason} ->
render conn, json: reason
end
end
以下是发送消息的库的一部分
defmodule Slack.Messages do
def format_simple_message(map) do
text = map.description <> " " <> map.commits
message = %{text: text}
end
def post_to_slack(map) do
Slack.post(:empty, map)
end
def send(map) do
map
|> format_simple_message
|> post_to_slack
end
end
我的HTTPoison处理
defmodule Slack do
use HTTPoison.Base
@endpoint "http://url.com"
def process_url() do
@endpoint
end
def process_response_body(body) do
body
|> Poison.decode! # Turns JSON into map
end
def process_request_body(body) do
body
|> Poison.encode! # Turns map into JSON
end
end
创建JSON的部分位于最后一个块中。
答案 0 :(得分:2)
您的请求有效负载似乎是两次JSON编码:
首先它返回输出字符串{"text":"..."}
,然后再次编码该字符串。 JSON不仅可以对对象进行编码,还可以对字符串进行编码,因此再次对上面的编码将提供"{\"text\":\"...\"}"
的输出。
也就是说,包含对象的JSON编码表示的字符串。
但是,Slack API需要{"text": "..."}
形式的对象,而不是字符串"..."
。后者仍然是有效的JSON,但就API而言,它不是有效的请求。这就是为什么你得到“无效的有效载荷”错误。
我不完全确定对象是第二次编码的位置。您上面的代码看起来没问题,但也许还有其他处理步骤不在这些代码段中。我建议您仔细检查代码,看看有两个Poison.encode!
调用应用于某些数据的路径。
process_request_body/1
中,您可以匹配参数 - 如果它已经是字符串,则跳过Poison.encode!
。为此,请使用以下代码:
def process_request_body(body) when is_binary(body), do: body
def process_request_body(body)
body
|> Poison.encode! # Turns map into JSON
end
这将通过逐字传递字符串,并对其他任何内容进行JSON编码。 但是,这可能很危险,因为字符串仍然是JSON编码的有效输入,因此如果要通过API发送纯JSON编码的字符串,则必须小心。同样,我建议修复根本原因,但根据您的情况,这种解决方法也可能是可行的。