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

如何在Rails中反序列化非标准JSON请求(非JSONAPI)

处理非标准JSON参数的Rails控制器方案

针对你遇到的帕斯卡命名、无根节点、嵌套层级深的JSON请求,按以下步骤处理:

1. 正确许可嵌套参数

首先解决参数强许可问题,嵌套结构需要在permit中明确声明层级,避免ActionController::ParameterMissing错误:

def permitted_params
  params.permit(
    :OrderID,
    :OrderType,
    DateTimes: [:DeliverDueDateTime],
    Area: {
      Code: [
        :ZipCode,
        AdditionalCodes: { ZipCode: [] }
      ]
    }
  )
end

之前的错误是因为require(:Area)用法不当——当参数存在但未正确许可嵌套结构时,require会误判参数为空,直接用上述方式完整许可所有层级即可。

2. 帕斯卡命名转蛇形命名

Rails模型字段通常使用蛇形命名(如order_id、deliver_due_datetime),需要递归转换所有层级的键名:

def deep_transform_keys_to_snake_case(hash)
  hash.transform_keys { |key| key.underscore }.transform_values do |value|
    case value
    when Hash
      deep_transform_keys_to_snake_case(value)
    when Array
      value.map { |item| item.is_a?(Hash) ? deep_transform_keys_to_snake_case(item) : item }
    else
      value
    end
  end
end

3. 处理日期格式(可选)

JSON中的日期格式可能不符合Rails默认解析规则,手动转换为Time对象:

snake_case_params = deep_transform_keys_to_snake_case(permitted_params)
# 转换配送截止时间
if snake_case_params.dig(:date_times, :deliver_due_datetime).present?
  snake_case_params[:date_times][:deliver_due_datetime] = Time.strptime(
    snake_case_params[:date_times][:deliver_due_datetime],
    "%Y/%m/%d %H:%M:%S"
  )
end

4. 保存到数据库

场景1:用JSON字段存储嵌套数据

如果你的Order模型用JSON字段(如date_times、area)存储嵌套内容,直接创建实例即可:

def create
  snake_case_params = deep_transform_keys_to_snake_case(permitted_params)
  # 可选:执行日期格式转换
  @order = Order.new(snake_case_params)
  
  if @order.save
    render json: @order, status: :created
  else
    render json: @order.errors, status: :unprocessable_entity
  end
end

场景2:拆分嵌套数据到单独字段

如果要将嵌套内容拆分到独立数据库字段(如deliver_due_datetime、zip_code),在模型中添加回调映射参数:

# Order模型
class Order < ApplicationRecord
  before_validation :map_nested_params

  private

  def map_nested_params
    self.deliver_due_datetime = Time.strptime(date_times['deliver_due_datetime'], "%Y/%m/%d %H:%M:%S") if date_times&.dig('deliver_due_datetime').present?
    self.zip_code = area.dig('code', 'zip_code') if area.present?
    # 按需映射其他嵌套字段
  end
end

关于ActiveModel Serializer的反序列化

AMS的反序列化确实支持自定义规则,但对于这种非标准格式,手动转换参数的方式更直接,无需额外配置序列化器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:15:58