Ruby 3.1.3+Faraday 2.7.5:response.body为何始终是JSON字符串而非解析对象?
问题
在Ruby 3.1.3与Faraday 2.7.5环境下,已配置Faraday启用JSON响应解析(faraday.response :json),但调用接口后response.body始终是JSON格式的字符串,而非解析后的Ruby哈希对象,必须手动执行JSON.parse才能得到预期结果。
客户端代码
def connection @connection ||= Faraday.new( url: url, headers: headers ) do |faraday| faraday.response :json faraday.request :json end end def headers { content_type: 'application/json', accept: 'application/json' } end def send_request connection.send(method) do |req| req.body = body end end
执行现象
调用接口后查看响应体:
[1] pry(#<App>)> response.body => "{\"data\":{\"date\":\"some_data\"}}"
必须手动解析才能得到Ruby哈希:
[2] pry(#<App>)> JSON.parse response.body => {"data"=>{"date"=>"some_data"}}
测试代码
let(:response_body) { { data: { date: 'some_data' } }.to_json } ... stub_request(:post, url) .with( body: body.to_json, headers: custom_headers ).to_return(status: status, body: response_body, headers: {}) end it 'POSTS to a url' do subject expect(a_request(:post, url)).to have_been_made end end
疑问:是测试代码存在问题,还是客户端代码的配置无法实现自动返回解析后的JSON对象?
分析与解决
问题出在测试代码的响应头配置,客户端代码本身的配置是正确的。
- Faraday的
json响应中间件默认仅在响应的Content-Type头为application/json时,才会自动将JSON字符串解析为Ruby哈希。 - 你的测试代码中,
to_return方法的headers参数为空,没有设置Content-Type: application/json,导致Faraday无法识别这是JSON响应,因此不会触发自动解析逻辑。
修复测试代码
在to_return中添加正确的响应头即可解决:
stub_request(:post, url) .with( body: body.to_json, headers: custom_headers ).to_return( status: status, body: response_body, headers: { 'Content-Type' => 'application/json' } # 新增响应头配置 )
可选优化:增强客户端兼容性
如果担心实际服务端返回的Content-Type不标准(比如返回text/json),可以修改客户端的json响应中间件配置,让它匹配更多类型的JSON响应:
faraday.response :json, content_type: /\bjson/ # 匹配任何包含"json"的Content-Type # 或者强制解析所有响应(不推荐,但极端场景可用) # faraday.response :json, content_type: '*/*'
内容的提问来源于stack exchange,提问作者I. Khan
相关产品推荐
相关产品推荐

