问题描述
我正在尝试将数据从JSON对象数组播种到数据库中。我有两个单独的数据库表-属性和单位(一个属性有许多单位)。通过API请求JSON数据,然后将其播种到数据库,我已经能够成功地针对属性信息(属性模型)执行此操作,但是ValuationReport属性在我的前端显示为字符串形式的JSON对象。>
以下是我正在使用的JSON数据的示例(出于演示目的,我已将该示例限制为3个对象的数组):
[
{
"PublicationDate": "17/09/2019","PropertyNumber": 2198231,"County": "CAVAN","LocalAuthority": "CAVAN COUNTY COUNCIL","Valuation": 15090,"Category": "OFFICE","Uses": "OFFICE (OVER THE SHOP),-","Address1": "77(1ST & 2ND FL) MAIN STREET","Address2": "CAVAN","Address3": "CO. CAVAN","Address4": "","Address5": "","CarPark": 0,"Xitm": 641927.73,"Yitm": 804638.3,"ValuationReport": [
{
"Level": "1","FloorUse": "RESTAURANT","Area": 112.25,"NavPerM2": 80,"Nav": 8980
},{
"Level": "2","Area": 98.57,"NavPerM2": 62,"Nav": 6111.34
}
]
},{
"PublicationDate": "17/09/2019","PropertyNumber": 1558322,"Valuation": 10200,"Uses": "OFFICE (OWN DOOR),"Address1": "23E MAIN STREET","Xitm": 641941.19,"Yitm": 804875.56,"ValuationReport": [
{
"Level": "0","FloorUse": "OFFICE(S)","Area": 127.55,"Nav": 10204
}
]
},"PropertyNumber": 2116802,"Valuation": 15140,HERITAGE / INTERPRETATIVE CENTRE","Address1": "LOCAL NO/MAP REF: 7AB","Address2": "MULLAGH","Address3": "BAILIEBORO CO. CAVAN","Xitm": 668656.19,"Yitm": 785281.05,"Area": 252.49,"NavPerM2": 60,"Nav": 15149.4
property_id: unit[property.id]
}
]
}
]
我遇到的困难是ValuationReport属性,它是JSON属性数组中每个元素的大小可变的数组。因此,某些属性将具有仅包含一个对象的ValuationReport数组,而其他属性将包含具有多个对象的ValuationReport对象。我想将每个ValuationReport数组中的每个嵌套对象保存到数据库(单元模型)中的单独单元中。
我已经使用JSONPath Gem尝试访问所需的元素,但是我做错了事。
当我运行'$ rails db:seed'时,它一直运行到一个点,并且出现以下错误:
Creating property 2198231
Creating unit.
rails aborted!
TypeError: no implicit conversion of String into Integer
/db/seeds.rb:62:in `[]'
/db/seeds.rb:62:in `block (2 levels) in properties'
/db/seeds.rb:58:in `each'
/db/seeds.rb:58:in `block in properties'
/db/seeds.rb:36:in `each'
/db/seeds.rb:36:in `properties'
/db/seeds.rb:207:in `<top (required)>'
bin/rails:4:in `require'
bin/rails:4:in `<main>'
Tasks: TOP => db:seed
(See full trace by running task with --trace)
以下是我的宝石文件中的相关宝石:
# REST Client for APIs
gem 'rest-client','~> 2.1'
# JSONPath - for acessing values in nested JSON objects.
gem 'jsonpath','~> 0.5.8'
我的数据库架构如下:
ActiveRecord::Schema.define(version: 2020_11_07_130018) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "properties",force: :cascade do |t|
t.date "publication_date"
t.string "property_number"
t.string "county"
t.string "local_authority"
t.decimal "valuation"
t.string "category"
t.string "uses"
t.string "address_1"
t.string "address_2"
t.string "address_3"
t.string "address_4"
t.string "address_5"
t.decimal "car_park"
t.decimal "xitm"
t.decimal "yitm"
t.datetime "created_at",precision: 6,null: false
t.datetime "updated_at",null: false
end
create_table "units",force: :cascade do |t|
t.string "level"
t.string "floor_use"
t.decimal "area"
t.decimal "nav_per_m2"
t.decimal "nav"
t.bigint "property_id"
t.datetime "created_at",null: false
t.index ["property_id"],name: "index_units_on_property_id"
end
add_foreign_key "units","properties"
end
我的seed.rb文件在下面。我尝试使用索引(i)来确保对象ValuationReport对象数组的循环为每个属性循环一次,并创建每个属性内存在的所有单元。
require 'rest-client'
require 'json'
require 'jsonpath'
# Define Method - API Request
def properties
response = RestClient.get('https://api.valoff.ie/api/Property/GetProperties?Fields=*&LocalAuthority=CAVAN%20COUNTY%20COUNCIL&CategorySelected=OFFICE&Format=csv&Download=false')
json = JSON.parse(response)
json.each do |property|
puts "Creating property #{property['PropertyNumber']}"
Property.create!(
publication_date: property['PublicationDate'],property_number: property['PropertyNumber'],county: property['County'],local_authority: property['LocalAuthority'],valuation: property['Valuation'],category: property['Category'],uses: property['Uses'],address_1: property['Address1'],address_2: property['Address2'],address_3: property['Address3'],address_4: property['Address4'],address_5: property['Address5'],car_park: property['CarPark'],xitm: property['Xitm'],yitm: property['Yitm'],units:
JsonPath.new('$.ValuationReport').on(property).each do |unit|
puts "Creating unit."
Unit.create!(
level: unit['$.Level'],floor_use: unit['$.FloorUse'],area: unit['$.Area'],nav_per_m2: unit['$.NavPerM2'],nav: unit['$.Nav'],property_id: unit['property.id']
)
end
)
end
end
# Call Method
properties
感谢您的时间和帮助!
解决方法
在这种情况下,您不需要JsonPath。我更新了您的脚本:
- 删除了JsonPath,转而使用
property['ValuationReport']
- 从json键中删除了
$.
- 首先您应该创建一个属性,然后以单位为单位使用其ID(或者,您可以在模型中设置
accepts_nested_attributes
)
require 'rest-client'
require 'json'
require 'jsonpath'
# Define Method - API Request
def properties
response = RestClient.get('https://api.valoff.ie/api/Property/GetProperties?Fields=*&LocalAuthority=CAVAN%20COUNTY%20COUNCIL&CategorySelected=OFFICE&Format=csv&Download=false')
json = JSON.parse(response)
json.each do |property|
puts "Creating property #{property['PropertyNumber']}"
property_model = Property.create!(
publication_date: property['PublicationDate'],property_number: property['PropertyNumber'],county: property['County'],local_authority: property['LocalAuthority'],valuation: property['Valuation'],category: property['Category'],uses: property['Uses'],address_1: property['Address1'],address_2: property['Address2'],address_3: property['Address3'],address_4: property['Address4'],address_5: property['Address5'],car_park: property['CarPark'],xitm: property['Xitm'],yitm: property['Yitm']
)
property['ValuationReport'].each do |unit|
puts "Creating unit."
property_model.units.create!(
level: unit['Level'],floor_use: unit['FloorUse'],area: unit['Area'],nav_per_m2: unit['NavPerM2'],nav: unit['Nav']
)
end
end
end
# Call Method
properties