You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:52:40