Ruby - 从json数组访问值

时间:2017-03-03 22:28:50

标签: ruby-on-rails arrays json ruby

我正在创建一个字段数组

def create_fields fields
  fields_list = []

  fields.each do |field|
    # puts "adding_field to array: #{field}"
    field_def = { field: field, data: { type: 'Text', description: '' }  }
    fields_list.push field_def
  end
  fields_list
end

fields_list被设置为 jsonb 字段。

让我说我传入

create_fields ['Ford', 'BMW', 'Fiat']

Json结果是一个数组:

{"field"=>"Ford", "data"=>{"type"=>"Text", "description"=>""}}
{"field"=>"BMW", "data"=>{"type"=>"Text", "description"=>""}}
{"field"=>"Fiat", "data"=>{"type"=>"Text", "description"=>""}}

如何从json数组访问'Ford'?我是否错误地创建了数组?有没有更好的方法来创建这个数组,以便我可以访问我想要的字段?

此断言通过assert_equal(3, fields.count)

然而我想要'福特'并检查它的属性,例如type ='Text',类型可以等于'Number'或其他。

4 个答案:

答案 0 :(得分:5)

带有指定参数的 create_fields 方法的结果如下:

[
  {:field=>"Ford", :data=>{:type=>"Text", :description=>""}}, 
  {:field=>"BMW", :data=>{:type=>"Text", :description=>""}},
  {:field=>"Fiat", :data=>{:type=>"Text", :description=>""}}
] 

这意味着如果您想访问属于" Ford"的行,您需要搜索它:

2.3.1 :019 > arr.select{|e| e[:field] == "Ford" }
 => [{:field=>"Ford", :data=>{:type=>"Text", :description=>""}}] 
2.3.1 :020 > arr.select{|e| e[:field] == "Ford" }[0][:data][:type]
 => "Text" 

这不是最佳选择,因为您需要搜索数组O(n)而不是使用哈希的优点。如果有例如:2"福特"你会得到一个包含2个元素的数组,更难处理字段值中的冲突。

如果你创建了这样的数组会更好:

def create_fields fields
  fields_list = []

  fields.each do |field|
    # puts "adding_field to array: #{field}"
    field_def = [field, { type: 'Text', description: '' }  ]
    fields_list.push field_def
  end
  Hash[fields_list]
end

如果您选择此版本,则可以访问以下成员:

2.3.1 :072 > arr = create_fields ['Ford', 'BMW', 'Fiat']
 => {"Ford"=>{:type=>"Text", :description=>""}, "BMW"=>{:type=>"Text", :description=>""}, "Fiat"=>{:type=>"Text", :description=>""}} 
2.3.1 :073 > arr["Ford"]
 => {:type=>"Text", :description=>""} 
2.3.1 :074 > arr["Ford"][:type]
 => "Text" 

以上两个例子都是Ruby词典/哈希。 如果你想从中创建一个JSON,你需要转换它:

2.3.1 :077 > require 'json'
 => true 
2.3.1 :078 > arr.to_json
 => "{\"Ford\":{\"type\":\"Text\",\"description\":\"\"},\"BMW\":{\"type\":\"Text\",\"description\":\"\"},\"Fiat\":{\"type\":\"Text\",\"description\":\"\"}}" 

答案 1 :(得分:3)

这是一种让我更有意义的基于已知密钥访问值的结构:

def create_fields fields
  fields_hash = {}

  fields.each do |field|
    fields_hash[field] = {type: 'Text', description: ''}
  end
  fields_hash
end

# The hash for fields_hash will look something like this:
{
  Ford: {
    type: "Text",
    description: ""
  },
  BMW: {...},
  Fiat: {...}
}

这将允许您访问类似的值:ruby中的fields[:Ford][:type]和JSON中的fields.Ford.type。听起来更容易返回Object而不是Array。您可以通过这种方式更轻松地访问基于键的值,并且如果需要,仍然可以选择循环访问对象。

答案 2 :(得分:1)

所以,你有方法的结果:

result = 
  [
   {"field"=>"Ford", "data"=>{"type"=>"Text", "description"=>""}},
   {"field"=>"BMW", "data"=>{"type"=>"Text", "description"=>""}},
   {"field"=>"Fiat", "data"=>{"type"=>"Text", "description"=>""}}
  ]

从中获取'福特',你可以使用简单的方法detect

result.detect { |obj| obj['field'] == 'Ford' }
#=> { "field"=>"Ford", "data"=>{"type"=>"Text", "description"=>""}

另外,我建议您编辑方法以使其更具可读性:

def create_fields(fields)
  fields.map do |field|
    {
      field: field,
      data: {
        type: 'Text',
        description: ''
      }
    }
  end
end

答案 3 :(得分:1)

显然,有几种方法可以创建或访问您的数据,但我总是倾向于选择最适合您应用程序的数据结构的开发人员。 在您的情况下,为了访问Ford哈希,您可以使用Ruby Histogram Screen shot方法:

ford = fields_list.detect{|field_hash| field_hash['field'] == 'Ford' }
ford['data'] # => {"type"=>"Text", "description"=>""}
ford['data']['type'] # => 'Text'