Rails项目开发环境JSON正常,Heroku生产环境JSON解析报错求助
从你描述的问题和代码来看,导致Heroku生产环境JSON解析失败的主要有两个核心问题,咱们一步步来解决:
1. 生产环境数据库配置不兼容Heroku
Heroku官方不支持SQLite作为生产数据库(SQLite是文件型数据库,Heroku的临时文件系统会导致数据丢失,且无法支持多线程/多实例部署),但你的database.yml里生产环境还在使用SQLite,这会导致Heroku上数据库根本无法正常工作——要么查询不到数据,要么直接抛出数据库连接错误,返回的是HTML格式的错误页面而非JSON,这就是你看到JSON.parse报错的根本原因。
修复步骤:
第一步:调整Gemfile,区分开发/测试和生产环境的数据库依赖
把sqlite3限制在开发和测试环境,添加PostgreSQL的pg gem到生产环境:
group :development, :test do gem 'sqlite3' end group :production do gem 'pg' end
第二步:更新database.yml的生产环境配置
替换原有的production配置为PostgreSQL适配的内容(Heroku会自动注入DATABASE_URL环境变量,无需手动填写用户名密码):
production: adapter: postgresql pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> url: <%= ENV['DATABASE_URL'] %>
第三步:重新安装依赖并部署
在本地执行:
bundle install --without production git add Gemfile Gemfile.lock config/database.yml git commit -m "Switch production database to PostgreSQL for Heroku" git push heroku main heroku run rails db:migrate
2. 控制器返回非标准JSON的潜在问题
当@jobs为空时,你当前返回的是render json: "Not Found", status: :ok——虽然Rails会把字符串转成JSON格式的"Not Found",但这不符合REST API的规范,而且如果数据库出错时返回的是HTML错误页,也会导致解析失败。咱们把它改成标准的JSON对象:
class Api::SuggestionsController < ApplicationController def jobs @jobs = Job.job_title_search(params[:q]) if @jobs.present? render json: @jobs, status: :ok else # 返回带错误信息的JSON对象,同时使用正确的404状态码 render json: { error: "No jobs found matching your query" }, status: :not_found end end end
另外,补充一个小细节:SQLite的LIKE是大小写不敏感的,但PostgreSQL的LIKE是大小写敏感的,如果你希望搜索行为和开发环境一致,可以把模型里的查询改成ILIKE:
def self.job_title_search(q) where('title ILIKE ?', "%#{q}%").select(:title, :label).distinct end
完成以上修改后,重新部署到Heroku,你的API应该就能正常返回可解析的JSON数据了。
内容的提问来源于stack exchange,提问作者jesica

