如何使用ruby

时间:2019-03-19 14:05:53

标签: ruby-on-rails json ruby serialization attributes

我有一个json对象。它具有多个字段“ passthrough_fields”,这对我来说是不必要的,我想将其删除。有没有办法过滤掉所有这些属性? JSON:

{
"type": "playable_item",
"id": "p06s0lq7",
"urn": "urn:bbc:radio:episode:p06s0mk3",
"network": {
    "id": "bbc_radio_five_live",
    "key": "5live",
    "short_title": "Radio 5 live",
    "logo_url": "https://sounds.files.bbci.co.uk/v2/networks/bbc_radio_five_live/{type}_{size}.{format}",
    "passthrough_fields": {}
},
"titles": {
    "primary": "Replay",
    "secondary": "Bill Shankly",
    "tertiary": null,
    "passthrough_fields": {}
},
"synopses": {
    "short": "Bill Shankly with Sue MacGregor in 1979 - five years after he resigned as Liverpool boss.",
    "medium": null,
    "long": "Bill Shankly in conversation with Sue MacGregor in 1979, five years after he resigned as Liverpool manager.",
    "passthrough_fields": {}
},
"image_url": "https://ichef.bbci.co.uk/images/ic/{recipe}/p06qbz1x.jpg",
"duration": {
    "value": 1774,
    "label": "29 mins",
    "passthrough_fields": {}
},
"progress": null,
"container": {
    "type": "series",
    "id": "p06qbzmj",
    "urn": "urn:bbc:radio:series:p06qbzmj",
    "title": "Replay",
    "synopses": {
        "short": "Colin Murray unearths classic sports commentaries and interviews from the BBC archives.",
        "medium": "Colin Murray looks back at 90 years of sport on the BBC by unearthing classic commentaries and interviews from the BBC archives.",
        "long": null,
        "passthrough_fields": {}
    },
    "activities": [],
    "passthrough_fields": {}
},
"availability": {
    "from": "2018-11-16T16:18:54Z",
    "to": null,
    "label": "Available for over a year",
    "passthrough_fields": {}
},
"guidance": {
    "competition_warning": false,
    "warnings": null,
    "passthrough_fields": {}
},
"activities": [],
"uris": [
    {
        "type": "latest",
        "label": "Latest",
        "uri": "/v2/programmes/playable?container=p06qbzmj&sort=sequential&type=episode",
        "passthrough_fields": {}
    }
],
"passthrough_fields": {}
}

有没有办法删除所有这些字段并将更新的json存储在新变量中?

3 个答案:

答案 0 :(得分:1)

You can do this recursively to tackle nested occurances of passthrough_fields, whether they're found in an array or a sub hash. Inline comments to explain things a little as it goes:

hash = JSON.parse(input) # convert the JSON to a hash

def remove_recursively(hash, *to_remove)
  hash.each do |key, val|
    hash.except!(*to_remove) # the heavy lifting: remove all keys that match `to_remove`

    remove_recursively(val, *to_remove) if val.is_a? Hash # if a nested hash, run this method on it

    if val.is_a? Array # if a nested array, loop through this checking for hashes to run this method on
      val.each { |el| remove_recursively(el, *to_remove) if el.is_a? Hash } 
    end
  end
end

remove_recursively(hash, 'passthrough_fields')

To demonstrate, with a simplified example:

hash =  { 
          "test" => { "passthrough_fields" => [1, 2, 3], "wow" => '123' }, 
          "passthrough_fields" => [4, 5, 6],
          "array_values" => [{ "to_stay" => "I am", "passthrough_fields" => [7, 8, 9]}]
        }

remove_recursively(hash, 'passthrough_fields')
#=> {"test"=>{"wow"=>"123"}, "array_values"=>[{"to_stay"=>"I am"}]}

remove_recursively(hash, 'passthrough_fields', 'wow', 'to_stay')
#=> {"test"=>{}, "array_values"=>[{}]}

This will tackle any arrays, and will dig for nested hashes however deep it needs to go.

It takes any number of fields to remove, in this case a single 'passthrough_fields'.

Hope this helps, let me know how you get on.

答案 1 :(得分:0)

我认为最简单的解决方案是:

  1. 将JSON转换为哈希(JSON.parse(input)

  2. 使用this answer扩展哈希的功能(将其保存在config/initializers/except_nested.rb中)

  3. 在第一步的哈希值上,调用:

    without_passthrough = your_hash.except_nested('passthrough_fields')

  4. 将哈希值隐藏为JSON(without_passthrough.to_json

请记住,它适用于直接嵌套在哈希中的passthrough_fields。在JSON中,包含以下部分:

"uris" => [
  {
    "type"=>"latest",
    "label"=>"Latest",
    "uri"=>"/v2/programmes/playable?container=p06qbzmj&sort=sequential&type=episode",
"passthrough_fields"=>{}
  }
]

在这种情况下,passthrough_fields将不会被删除。您必须找到一个更复杂的解决方案:)

答案 2 :(得分:0)

You can do something like this:

def nested_except(hash, except_key)
  sanitized_hash = {}
  hash.each do |key, value|
    next if key == except_key
    sanitized_hash[key] = value.is_a?(Hash) ? nested_except(value, except_key) : value
  end
  sanitized_hash
end

json = JSON.parse(json_string)
sanitized = nested_except(json, 'passthrough_fields')

See example:

json = { :a => 1, :b => 2, :c => { :a => 1, :b => { :a => 1 } } }
nested_except(json, :a)
# => {:b=>2, :c=>{:b=>{}}}

This helper can easily be converted to support multiple keys to except, simply by except_keys = Array.wrap(except_key) and next if except_keys.include?(key)