【问题标题】:Ruby JSON parse "sub-keys"?Ruby JSON解析“子键”?
【发布时间】:2016-11-25 17:00:37
【问题描述】:

我正在尝试解析一个我已经解析了一段时间的现有 JSON 的附加键,但最近我们添加了一个新键“metric_details”,它分隔各个区域,它包含 2 个键以及“performance_score”和“compliance_score”。现在,我已经能够毫无问题地解析它,但我一生都无法弄清楚如何提取 metric_details 并将分数导出到我的 RDS 中。

解析代码:

   states = %w(CA TX)
results_warehouses = states
creds = User_creds

data_to_write = []
results_warehouses.each do |code|

  dashboard = "https://sample.website.com/states/scorecard.json?state_id=#{code}"
  puts "Pulling from #{dashboard}"

  begin
    data  =  HTTParty.get(dashboard, :basic_auth=> {:username => creds.public.text, :password => creds.private.text})
  rescue
    puts "Could not fetch data for #{code}. Skipping..."
    next
  end

  types = %w(pack ship)
  types.each do |type|

    metric = data[type]
    next if metric.nil?
    metric.sort.each do |key|
      state_id                = key['state_id']
      raw_date                = key['date'].to_date
      # Can't figure how to parse this metric_details          = key['metric_details']
      performance_score       = key['performance_score']
      audit_compliance_score  = key['compliance_score']

      data_to_write << "('#{state_id.to_s}',
                         '#{raw_date.to_s}',
                         '#{type.to_s}',
                         '#{metric_details.to_s}',
                         '#{performance_score.to_s}',
                         '#{compliance_score.to_s}')"
      puts data_to_write
    end
  end

  unless data_to_write.empty?
    puts 'Inserting data'
    db_conn   = DatabaseConnect.new
    db_client = db_conn.connect_mysql
    ins = "INSERT IGNORE INTO `data`.`scoring` VALUES #{data_to_write.join(',')}"
    db_client.query(ins)
  end
  db_conn.disconnect
  puts 'Completed.'
end

puts 'All done!'

而且,这是我正在分解的 JSON,它没有任何问题,直到我尝试获取各个指标详细信息

"pack":[
{
"state_id":"CA",
"total_score":90,
"compliance_score":100,
"performance_score":80,
"date":"2016-11-24T00:00:00.000-08:00",
"metric_details":{
"Damages":{
"performance_score":91,
"compliance_score":100
},
"Error Indicators":{
"performance_score":100,
"compliance_score":"N/A"
},
"Unverified":{
"performance_score":75,
"compliance_score":100
},
"Pack Miss":{
"performance_score":54,
"ompliance_score":100
}
}
}
],

而且我的表结构相当简单:

本质上想要这样格式化:

CA,2016 年 11 月 25 日,包装,损害赔偿,75、100

state_id、raw_date、类型、metric_details、performance_score、compliance_score

感谢您的帮助!

更新:

states = %w(CA TX)
results_warehouses = states
creds = User_creds

data_to_write = []
results_warehouses.each do |code|

  dashboard = "https://sample.website.com/states/scorecard.json?state_id=#{code}"
  puts "Pulling from #{dashboard}"

  begin
    data  =  HTTParty.get(dashboard, :basic_auth=> {:username => creds.public.text, :password => creds.private.text})
  rescue
    puts "Could not fetch data for #{code}. Skipping..."
    next
  end

  types = %w(pack ship)
  types.each do |type|

    metric = data[type]
    next if metric.nil?
    metric.sort.each do |key|
      state_id                = key['state)ud']
      raw_date                = key['date'].to_date
      hash                    = key['metric_details']
      damages                 = hash['Damages']
      performance_score       = damages['performance_score']
      audit_compliance_score  = damages['compliance_score']

      data_to_write << "('#{state_id.to_s}',
                         '#{raw_date.to_s}',
                         '#{type.to_s}',
                         '#{metric_details.to_s}',
                         '#{performance_score.to_s}',
                         '#{audit_compliance_score.to_s}')"
      puts data_to_write
    end
  end

  unless data_to_write.empty?
    puts 'Inserting data'
    db_conn   = DatabaseConnect.new
    db_client = db_conn.connect_mysql
    ins = "INSERT IGNORE INTO `data`.`scoring` VALUES #{data_to_write.join(',')}"
    db_client.query(ins)
  end
  db_conn.disconnect
  puts 'Completed.'
end

puts 'All done!'

【问题讨论】:

    标签: json ruby parsing


    【解决方案1】:

    key['metric_details'] 返回哈希值:

    {
      "Damages":{
        "performance_score":91,
        "compliance_score":100
      },
      "Error Indicators": {
        "performance_score":100,
        "compliance_score":"N/A"
      },
      ...
      ...
    }
    

    因此,您需要查找该哈希中的信息:

    hash = key['metric_details']
    damages = hash['Damages']
    performance_score = damages['performance_score']
    compliance_score = damgages['compliance_score']
    

    这是一个完整的例子:

    require 'json'
    
    data = %Q{
    {"pack":[
    {
    "state_id": "CA",
    "total_score":90,
    "compliance_score":100,
    "performance_score":80,
    "date":"2016-11-24T00:00:00.000-08:00",
    "metric_details":{
    "Damages":{
    "performance_score":91,
    "compliance_score":100
    },
    "Error Indicators":{
    "performance_score":100,
    "compliance_score":"N/A"
    },
    "Unverified":{
    "performance_score":75,
    "compliance_score":100
    },
    "Pack Miss":{
    "performance_score":54,
    "ompliance_score":100
    }
    }
    }
    ]
    
    }
    }
    
    data = JSON.parse data
    data_to_write = ""
    
    types = %w(pack ship)
    types.each do |type|
      metric = data[type]
      next if metric.nil?
    
      metric.sort.each do |hash|
        state_id                = hash['state_id']
        raw_date                = hash['date']
        # Can't figure how to parse this metric_details          = key['metric_details']
        #performance_score       = key['performance_score']
        #audit_compliance_score  = key['compliance_score']
        metric_details = hash['metric_details']
        damages_hash = metric_details['Damages']
        performance_score = damages_hash['performance_score']
        compliance_score = damages_hash['compliance_score']
    
        data_to_write << "('#{state_id}',
                           '#{raw_date}',
                           '#{type}',
                           '#{performance_score}',
                           '#{compliance_score}')"
        puts data_to_write
      end
    end
    
    --output:--
    ('CA',
                           '2016-11-24T00:00:00.000-08:00',
                           'pack',
                           '91',
                           '100')
    

    【讨论】:

    • 这可以在初始循环中实现吗?接下来如果metric.nil? metric.sort.each 做 |key|仓库id = key['warehouse_id'] raw_date = key['date'].to_date hash = key['metric_details'] damages = hash['Damages'] performance_score = damages['performance_score'] audit_compliance_score = damages['compliance_score']
    • @Spartacus38,我认为您可以将该代码放在您的评论所在的位置,然后删除评论下的两行。
    • lib/script/metric_details.rb:38:in block (3 levels) in &lt;top (required)&gt;': undefined local variable or method metric_details' for main:Object (NameError) from lib/script/metric_details.rb:27:in each' from lib/script/metric_details.rb:27:in block (2 个级别) in ' from lib/script/metric_details.rb:23:in each' from lib/script/metric_details.rb:23:in block in ' from lib/script/metric_details.rb:7:in each' from lib/script/metric_details.rb:7:in '
    • @Spartacus38,我在答案末尾发布了一个示例。
    • 如果你知道所有的键名,那么你可以在哈希中查找它们,例如metric_details['Damages'], metric_details['Unverified'], etc.如果你不知道所有的键名,那么你如何在 metric_details 这样的散列中遍历键/值对?
    猜你喜欢
    • 2011-11-24
    • 1970-01-01
    • 2012-04-30
    • 1970-01-01
    • 2019-08-07
    • 2014-04-03
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多