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

Rails调用含嵌套数据的API执行db:seed报错TypeError: String无法隐式转为Integer

错误原因

你遇到的报错有三个核心诱因:

  1. 接口返回结构解析错误:你调用的接口返回的外层不是直接的数组,而是包裹了data字段的对象,结构为{"data": [quote1, quote2...]}。你直接将JSON解析后的哈希对象当做数组调用each迭代,迭代时拿到的question实际是哈希的键(字符串类型),调用question["id"]相当于尝试用字符串作为索引访问字符串,触发了类型转换错误。
  2. 字段类型不匹配:你数据库中character字段是字符串类型,但是API返回的character是嵌套哈希结构,直接赋值给字符串字段无法正常存储,也会触发类型错误。
  3. 字段名匹配错误:API返回的唯一标识字段是下划线开头的_id,不是你代码里写的id,取值会为空。
解决方案

步骤1:选择字段存储方案(二选一)

方案A:仅存储完整姓名(适合只需要展示姓名的场景)

不需要修改现有表结构,直接在种子文件中把嵌套哈希拼接为全名字符串即可。

方案B:存储完整character结构(适合需要前端单独获取firstname、lastname的场景)

生成新的迁移文件修改字段类型为jsonb(PostgreSQL原生支持,性能更优):

class ChangeCharacterToBeJsonInQuestions < ActiveRecord::Migration[6.1]
  def change
    change_column :questions, :character, :jsonb, default: {}
  end
end

执行迁移命令:
rails db:migrate

步骤2:修改种子文件代码

require 'rest-client'

resp = RestClient::Request.execute(method: :get,
url: "https://officeapi.dev/api/quotes/",
headers:{
    'Content-Type': 'application/json'
})

resp_hash = JSON.parse(resp)
# 取外层data字段拿到实际的quote数组
resp_array = resp_hash["data"]

resp_array.each do |question|
  # 方案A用这段代码拼接姓名
  # character_val = "#{question.dig('character', 'firstname')} #{question.dig('character', 'lastname')}"
  # 方案B用这段代码直接取完整嵌套哈希
  character_val = question["character"]

  Question.create(
    # 注意API主键是下划线开头的_id
    id: question["_id"],
    content: question["content"],  
    character: character_val
  )
end

如果你不需要和第三方API的ID保持一致,可以删除id: question["_id"]这行,让Rails自动生成自增主键,避免ID冲突问题。

步骤3:可选调整控制器返回

如果选择方案B存储JSON结构,控制器无需修改即可返回完整的character嵌套结构,前端可以直接读取character.firstname、character.lastname使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 15:39:03