使用 :include 时将 Rails 中的 JSON 数据展平
Flatten JSON data in Rails when using :include
我使用“#111 Advanced Search Form (revised)”教程向我的应用程序添加了一个 "Advance Search",并为其创建了一个 API。一切正常,但现在我正在尝试显示 JSON 数据。
这是 cURL 命令:
curl -v -H 'Content-Type: application/json' -H 'Accept: application/json' -X
GET http://0.0.0.0:3000/api/searches/129
这是 Curl 命令的结果(请注意括号[ ],因此这是一个哈希数组。):
[{"id":4,"state_id":5,"name":"School Liason Officer","created_at":"2014-10-16T03:13:00.000Z",
"updated_at":"2014-10-16T03:13:00.000Z","state":{"name":"California"}}]
但我想更改 JSON 结果,以便状态名称以某种方式与 JSON 数据扁平化。
有谁知道我该怎么做,或者是否有可能展平数据?
这是我想要的示例:
[{"id":4,"state":"California","name":"School Liason Officer","created_at":"2014-10-16T03:13:00.000Z",
"updated_at":"2014-10-16T03:13:00.000Z"}]
型号:
class State < ActiveRecord::Base
has_many :district_resources
end
class DistrictResource < ActiveRecord::Base
belongs_to :state
end
class Search < ActiveRecord::Base
def district_resources
@district_resources ||= find_district_resources
end
def find_district_resources
district_resources = DistrictResource.order(:name)
district_resources = district_resources.where(state_id: state_id) if state_id.present?
district_resources
end
end
API 控制器:
module Api
module V1
class SearchesController < ApplicationController
respond_to :json
def show
@search = Search.find(params[:id])
@searches = []
(@searches << @search.district_resources).flatten!
json = @searches.to_json
def flatten_hash(h)
new_hash = {}
###I get an error here undefined method `each_pair' for Array
h.each_pair do |key, val|
if val.is_a?(Hash)
new_hash[key] = val.values.join(',')
else
new_hash[key] = val
end
end
new_hash
end
flattened_hash = flatten_hash(JSON.parse(json))
flattened_hash.delete("state_id")
respond_to do |format|
###How can i merge the state name with the json results
format.json { render :json => flattened_hash.to_json(:include => [:state => {:only => [:name]}] )}
end
end
end
end
end
错误
undefined method `each_pair' for #<Array:0x007f8d727b5168>
您可以随心所欲地操作它,即将它传递给另一个变量,使用方法调用等:
my_json["state"] = my_json["state"]["name"]
my_json.delete("state_id")
这会将 state =>
设置为 name =>
的值,然后删除不需要的 state_id =>
我支持 Beartech 的评论,但假设这是不可能的,那么就这样做
require 'json'
def flatten_hash(h)
new_hash = {}
h.each_pair do |key, val|
if val.is_a?(Hash)
new_hash[key] = val.values.join(',')
else
new_hash[key] = val
end
end
new_hash
end
json = '{"id":4,"state_id":5,"name":"School Liason Officer","created_at":"2014-10-16T03:13:00.000Z", "updated_at":"2014-10-16T03:13:00.000Z","state":{"name":"California"}}'
flattened_hash = flatten_hash(JSON.parse(json).to_hash)
flattened_hash.delete("state_id")
给予
{"id"=>4, "name"=>"School Liason Officer", "created_at"=>"2014-10-16T03:13:00.000Z", "updated_at"=>"2014-10-16T03:13:00.000Z", "state"=>"California"}
我结合了上面的两个答案来得到我需要的。 :)
def show
@search = Search.find(params[:id])
@searches = []
(@searches << @search.district_resources).flatten!
json = @searches.to_json(:include => [:state => {:only => [:name]}] )
def flatten_hash(h)
new_hash = []
h.each do |val|
if val.is_a?(Hash)
val["state"] = val["state"]["name"]
val.delete("state_id")
(new_hash << val).flatten!
else
new_hash << val
end
end
new_hash
end
flattened_hash = flatten_hash(JSON.parse(json))
respond_to do |format|
format.html
#(:include => [:state => {:only => [:name]}] )
format.json { render :json => flattened_hash.to_json }
end
end
我使用“#111 Advanced Search Form (revised)”教程向我的应用程序添加了一个 "Advance Search",并为其创建了一个 API。一切正常,但现在我正在尝试显示 JSON 数据。
这是 cURL 命令:
curl -v -H 'Content-Type: application/json' -H 'Accept: application/json' -X
GET http://0.0.0.0:3000/api/searches/129
这是 Curl 命令的结果(请注意括号[ ],因此这是一个哈希数组。):
[{"id":4,"state_id":5,"name":"School Liason Officer","created_at":"2014-10-16T03:13:00.000Z",
"updated_at":"2014-10-16T03:13:00.000Z","state":{"name":"California"}}]
但我想更改 JSON 结果,以便状态名称以某种方式与 JSON 数据扁平化。
有谁知道我该怎么做,或者是否有可能展平数据?
这是我想要的示例:
[{"id":4,"state":"California","name":"School Liason Officer","created_at":"2014-10-16T03:13:00.000Z",
"updated_at":"2014-10-16T03:13:00.000Z"}]
型号:
class State < ActiveRecord::Base
has_many :district_resources
end
class DistrictResource < ActiveRecord::Base
belongs_to :state
end
class Search < ActiveRecord::Base
def district_resources
@district_resources ||= find_district_resources
end
def find_district_resources
district_resources = DistrictResource.order(:name)
district_resources = district_resources.where(state_id: state_id) if state_id.present?
district_resources
end
end
API 控制器:
module Api
module V1
class SearchesController < ApplicationController
respond_to :json
def show
@search = Search.find(params[:id])
@searches = []
(@searches << @search.district_resources).flatten!
json = @searches.to_json
def flatten_hash(h)
new_hash = {}
###I get an error here undefined method `each_pair' for Array
h.each_pair do |key, val|
if val.is_a?(Hash)
new_hash[key] = val.values.join(',')
else
new_hash[key] = val
end
end
new_hash
end
flattened_hash = flatten_hash(JSON.parse(json))
flattened_hash.delete("state_id")
respond_to do |format|
###How can i merge the state name with the json results
format.json { render :json => flattened_hash.to_json(:include => [:state => {:only => [:name]}] )}
end
end
end
end
end
错误
undefined method `each_pair' for #<Array:0x007f8d727b5168>
您可以随心所欲地操作它,即将它传递给另一个变量,使用方法调用等:
my_json["state"] = my_json["state"]["name"]
my_json.delete("state_id")
这会将 state =>
设置为 name =>
的值,然后删除不需要的 state_id =>
我支持 Beartech 的评论,但假设这是不可能的,那么就这样做
require 'json'
def flatten_hash(h)
new_hash = {}
h.each_pair do |key, val|
if val.is_a?(Hash)
new_hash[key] = val.values.join(',')
else
new_hash[key] = val
end
end
new_hash
end
json = '{"id":4,"state_id":5,"name":"School Liason Officer","created_at":"2014-10-16T03:13:00.000Z", "updated_at":"2014-10-16T03:13:00.000Z","state":{"name":"California"}}'
flattened_hash = flatten_hash(JSON.parse(json).to_hash)
flattened_hash.delete("state_id")
给予
{"id"=>4, "name"=>"School Liason Officer", "created_at"=>"2014-10-16T03:13:00.000Z", "updated_at"=>"2014-10-16T03:13:00.000Z", "state"=>"California"}
我结合了上面的两个答案来得到我需要的。 :)
def show
@search = Search.find(params[:id])
@searches = []
(@searches << @search.district_resources).flatten!
json = @searches.to_json(:include => [:state => {:only => [:name]}] )
def flatten_hash(h)
new_hash = []
h.each do |val|
if val.is_a?(Hash)
val["state"] = val["state"]["name"]
val.delete("state_id")
(new_hash << val).flatten!
else
new_hash << val
end
end
new_hash
end
flattened_hash = flatten_hash(JSON.parse(json))
respond_to do |format|
format.html
#(:include => [:state => {:only => [:name]}] )
format.json { render :json => flattened_hash.to_json }
end
end