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

Rails控制器使用render json时哈希键显示异常排查

问题根因

JSON规范明确要求所有对象的键必须是字符串类型,两个错误操作直接导致了渲染异常:

  • 直接使用ActiveRecord实例(OpsHeader对象)作为哈希键时,JSON序列化器会自动调用对象的to_s方法转成字符串,而OpsHeader的默认to_s输出就是#<OpsHeader:内存地址>格式,最终键就变成了无意义的对象标识。
  • 后续把键替换为属性哈希后,Ruby原生哈希同样不支持嵌套哈希作为自身键,序列化时会把整个嵌套哈希直接转成无意义的字符串,才会出现一长串哈希内容当键的奇怪输出。
    另外你写的双层嵌套循环遍历所有站点和行项的逻辑效率极低,数据量稍大就会出现严重的性能问题。

解决方案

1. 调整数据结构,符合JSON规范

不要使用ActiveRecord对象、嵌套哈希作为哈希键,两种常用的结构化方案可选:

方案A(推荐):使用数组承载所有站点的聚合信息

每个站点作为独立的数组元素,把行项数组作为站点信息的嵌套字段,不需要自定义键值映射,组装效率更高:

# 预加载关联行项,避免N+1查询
stops = OpsHeader
  .joins(ops_stop_rec: :driver_header)
  .includes(ops_stop_rec: :ops_line_items)
  .select(
    :pb_net_rev, :pbbname, :ops_driver1, :pb_id,
    :ops_stop_id, :dh_first_name, :dh_last_name
  )
  .where(ops_stop_rec: { ops_arrive_time: params[:startDate]..params[:endDate] })

# 结构化组装返回结果
render json: stops.map do |stop|
  {
    # 展开站点基础属性,和line_items字段合并为单个哈希
    **stop.attributes.slice(
      "pb_id", "pbbname", "pb_net_rev", "ops_driver1",
      "ops_stop_id", "dh_first_name", "dh_last_name"
    ),
    # 匹配站点下的行项数组,无匹配时可按需求返回空数组或null
    line_items: (
      matched_lines = stop.ops_stop_rec.ops_line_items
        .select { |line| line.ops_stop_id == stop.ops_stop_id && line.ops_driver1 == stop.ops_driver1 }
      matched_lines.empty? ? nil : matched_lines.as_json(only: [:opl_amount, :ops_type, :ops_stop_id, :ops_order_id, :ops_driver1])
    )
  }
end

方案B:保留哈希键值结构

如果一定要使用哈希做返回结构,就拿站点的唯一标识(如ops_stop_id)转成字符串当键,值为包含站点信息和行项的对象,符合JSON的键格式要求:

merger = {}
stops.each do |stop|
  merger[stop.ops_stop_id.to_s] = {
    stop_info: stop.attributes.slice(
      "pb_id", "pbbname", "pb_net_rev", "ops_driver1",
      "ops_stop_id", "dh_first_name", "dh_last_name"
    ),
    line_items: nil
  }
end

# 后续把匹配的行项push到对应键的line_items数组里即可
# 最后直接 render json: merger

补充说明

你在binding.pry中看到的正常哈希结构,是Ruby原生哈希的表现——Ruby本身支持任意类型对象作为哈希键,这和JSON序列化的规则完全不同,pry中可正常查看的结构不代表能直接渲染为合法可读的JSON。

内容的提问来源于stack exchange,提问作者AttemptedMastery

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 12:15:03