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

Phoenix控制器测试:传入Map列表报错及JSON被_json键包裹问题

Phoenix控制器测试:传入Map列表的正确方式

问题分析

直接传递列表触发ArgumentError

当你直接将Map列表作为put/3的参数时,Phoenix测试工具会默认将参数视为表单数据(application/x-www-form-urlencoded),而表单数据要求参数是键值对结构(Map)。:maps.from_list/1尝试将你的列表转换为Map时,因为列表元素是Map而非键值元组,所以抛出ArgumentError。

手动编码JSON后数据被包裹在_json键中

手动编码JSON字符串并传入put/3时,Phoenix依然会将其当作表单参数处理——它无法识别顶级JSON数组,会自动将这个JSON字符串作为值,存入_json键对应的Map中,这就导致控制器收到的数据被额外包裹。

正确解决方案

要发送顶级JSON数组的请求,需要直接设置请求体为编码后的JSON字符串,同时指定正确的Content-Type,而不是将其作为put/3的参数传递。使用put_raw/3方法(Phoenix.ConnTest提供)来发送请求:

params =
  [
    %{"id" => 1, "sum" => 6},
    %{"id" => 2, "sum" => 4}
  ]
  |> Jason.encode!()

conn =
  conn
  |> put_req_header("content-type", "application/json")
  |> put_raw(Routes.stat_path(conn, :replace_all), params)

额外注意事项

确保你的应用端点(endpoint.ex)已配置JSON解析器,这样控制器才能正确解析请求体:

# 在endpoint.ex中
plug Plug.Parsers,
  parsers: [:json, :urlencoded, :multipart],
  pass: ["*/*"],
  json_decoder: Jason

此时控制器中通过conn.body_params就能拿到预期的Map列表:

[%{"id" => 1, "sum" => 6}, %{"id" => 2, "sum" => 4}]

内容的提问来源于stack exchange,提问作者denis.peplin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 15:25:25