Elixir中Plug.Parser无法读取解析JSON请求体问题求助
为什么我的Elixir Plug服务器中conn.body_params返回%Plug.Conn.Unfetched{aspect: :body_params}?
这个问题我之前也碰到过,核心原因主要有两个,咱们一步步拆解解决:
1. 最关键的问题:请求的JSON格式不合法
你用curl发送的请求体{one: 1, two: 2}是JavaScript对象语法,并非标准JSON格式。标准JSON要求所有键名必须用双引号包裹,正确写法应该是{"one": 1, "two": 2}。
Plug.Parsers的JSON解析器(你这里用的是Jason)遇到非法JSON时会直接跳过解析流程,导致body_params始终处于未获取的%Plug.Conn.Unfetched{}状态。
2. 确认Plug.Parsers的执行顺序(你的代码这里是对的,还是提一下避坑)
你已经把Plug.Parsers放在:match之后、:dispatch之前,这个顺序完全正确——:match先匹配对应路由,Plug.Parsers再解析请求体,最后:dispatch处理请求。如果顺序颠倒或者中间有其他Plug提前读取了请求体,也会导致解析失败,但从你给出的代码看,这部分没问题。
修正方案
第一步:用合法JSON格式发送请求
修改curl命令,把请求体改成标准JSON,并用单引号包裹(避免shell解析双引号):
curl -H "Content-Type: text/json" -d '{"one": 1, "two": 2}' 127.0.0.1:8080/test
第二步(可选):添加错误处理,方便调试
给Plug.Parsers加上错误处理器,以后遇到解析错误时能直接定位问题,不用瞎猜:
defmodule Test.Router do use Plug.Router require Logger plug :match plug Plug.Parsers, parsers: [:json], pass: ["application/json", "text/json"], json_decoder: Jason, error_handler: __MODULE__ # 新增错误处理器配置 plug :dispatch post "/test" do Logger.debug inspect(conn.body_params) conn |> put_resp_content_type("text/plain") |> send_resp(204, "Got it") end # 实现错误处理函数 def handle_errors(conn, {:bad_request, reason}) do Logger.error("JSON解析失败:#{inspect(reason)}") conn |> send_resp(400, "无效的JSON请求体") end end
这样再发送非法JSON时,服务器会返回400状态码,同时日志里会打印具体错误原因,调试效率会高很多。
当你用合法JSON发送请求后,conn.body_params就会正确返回解析后的%{"one" => 1, "two" => 2},而不是那个Unfetched结构体了。
内容的提问来源于stack exchange,提问作者Kamen
相关产品推荐
相关产品推荐

