Как удалить несколько атрибутов из json, используя ruby - PullRequest
1 голос
/ 19 марта 2019

У меня есть объект 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 ]

1 голос
/ 19 марта 2019

Вы можете сделать это рекурсивно, чтобы справиться с вложенными вхождениями passthrough_fields, независимо от того, найдены они в массиве или под хэше. Встроенные комментарии, чтобы объяснить вещи немного, как это идет:

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')

Для демонстрации на упрощенном примере:

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"=>[{}]}

Это займется любыми массивами и будет искать вложенные хэши, сколь бы глубокими они ни были.

Требуется любое количество полей для удаления, в данном случае одного 'passthrough_fields'.

Надеюсь, это поможет, дайте мне знать, как вы поживаете.

0 голосов
/ 19 марта 2019

Вы можете сделать что-то вроде этого:

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')

См. Пример:

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

Этот помощник может быть легко преобразован для поддержки нескольких ключей, кроме, просто с помощью except_keys = Array.wrap(except_key) иnext if except_keys.include?(key)

0 голосов
/ 19 марта 2019

Я думаю, что самым простым решением было бы:

  1. преобразовать JSON в хеш (JSON.parse(input))

  2. использовать этот ответ для расширения функциональности Hash (сохраните его в config/initializers/except_nested.rb)

  3. в хэше с 1-го шага, позвоните:

    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 не будет удален.Вы должны найти более сложное решение:)

...