1

I have a json object. It has multiple fields "passthrough_fields" which is unnecessary for me and I want to remove them. Is there a way to get all those attributes filtered out? 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": {}
}

Is there a way I can remove all those fields and store the updated json in a new variable?

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Did this help at all @NipunTanay? Believe it does all you're after - let me know how you get on with it.
It worked like a charm @SRack. Thanks a lot for it.
0

I think that the easiest solution would be to:

  1. convert JSON into hash (JSON.parse(input))

  2. use this answer to extend the functionality of Hash (save it in config/initializers/except_nested.rb)

  3. on the hash from 1st step, call:

    without_passthrough = your_hash.except_nested('passthrough_fields')

  4. covert hash to JSON (without_passthrough.to_json)

Please keep in mind that it will work for passthrough_fields that is nested directly in hashes. In your JSON, you have the following part:

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

In this case, the passthrough_fields will not be removed. You have to find a more sophisticated solution :)

Comments

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.