2

After parsing a URL parameter for partial responses, e.g. ?fields=name,id,another(name,id),date, I'm getting back an arbitrarily nested list of strings, representing the individual keys of a nested JSON object:

['name', 'id', ['another', ['name', 'id']], 'date']

The goal is to map that parsed 'graph' of keys onto an original, larger dict and just retrieve a partial copy of it, e.g.:

input_dict = {
  "name": "foobar",
  "id": "1",
  "another": {
    "name": "spam",
    "id": "42",
    "but_wait": "there is more!"
  },
  "even_more": {
    "nesting": {
      "why": "not?"
    }
  },
  "date": 1584567297
}

should simplyfy to:

output_dict = {
  "name": "foobar",
  "id": "1",
  "another": {
    "name": "spam",
    "id": "42"
  },
  "date": 1584567297,
}

Sofar, I've glanced over nested defaultdicts, addict and glom, but the mappings they take as inputs are not compatible with my list (might have missed something, of course), and I end up with garbage.

How can I do this programmatically, and accounting for any nesting that might occur?

rypel
  • 4,686
  • 2
  • 25
  • 36
  • So the original nested dictionary is output? – Dani Mesejo Mar 18 '20 at 22:19
  • @DaniMesejo the upper dict is the original (input) where the list of keys should be applied to, in order get the bottom dict (output). i'll edit my description to make that clearer. – rypel Mar 18 '20 at 22:26

1 Answers1

2

you can use:

def rec(d, f):

    result = {}
    for i in f:
        if isinstance(i, list):
            result[i[0]] = rec(d[i[0]], i[1])
        else:
            result[i] = d[i]

    return result

f = ['name', 'id', ['another', ['name', 'id']], 'date']
rec(input_dict, f)

output:

{'name': 'foobar',
 'id': '1',
 'another': {'name': 'spam', 'id': '42'},
 'date': 1584567297}

here the assumption is that on a nested list the first element is a valid key from the upper level and the second element contains valid keys from a nested dict which is the value for the first element

kederrac
  • 16,819
  • 6
  • 32
  • 55