0

I have a list of fields like so -

required_fields = ["server['server_name']","server['server_info']['asset_type']['display_name']",
                   "server['asset_status']['display_name']", "server['record_owner']['group_name']",
                   "server['server_total_cost_of_ownership']['description']",
                   "server['primary_business_owner']['name']", "server['environment']['display_name']",
                   "server['is_virtual']", "server['managed_by']['display_name']",
                   "server['server_info']['billable_ibm']", "server['server_info']['billing_sub_type']['display_name']",
                   "server['server_info']['serial_number']", "", "server['location']['display_name']",
                   "server['inception_date']", "server['server_info']['decommission_date']" ]

Each one represents a key in a JSON file I want to get the values out of to transform into CSV. If I do the following:

for server in server_list:
    for item in required_fields:
        print item

all is does is return the string value from each item in the key. What I want it to do is give me the value that is associated with the key.

So as an example in the above code print item is giving me server['server_name'] and not torservapp001

whoisearth
  • 4,080
  • 13
  • 62
  • 130
  • Possible duplicate of [How do I do variable variables in Python?](http://stackoverflow.com/questions/1373164/how-do-i-do-variable-variables-in-python) – Morgan Thrapp Jul 07 '16 at 14:12
  • I can't see `torservapp001` anywhere in your data – th3an0maly Jul 07 '16 at 14:14
  • 1
    Do you want to *execute* `server['server_name']` to get `torservapp001`? – MisterMiyagi Jul 07 '16 at 14:15
  • @th3an0maly - the example return value is in the json. I don't have the requests getting the json but I do have the raw json and the values are there. ie. I can do `print server['server_name']` and it gives me the value. – whoisearth Jul 07 '16 at 14:15
  • @MisterMiyagi - Yes! – whoisearth Jul 07 '16 at 14:16
  • 1
    There's a standard `json` module that can convert JSON strings (or files) into Python objects safely. There's no need to use `eval` for that! – PM 2Ring Jul 07 '16 at 15:29
  • @PM2Ring The thing he wants to interpret **is not JSON**! It's a list of python statements. If anything, tell him how to safely `re` the statement to get `name, key1, key2, ...`. – MisterMiyagi Jul 08 '16 at 07:48
  • @MisterMiyagi: The question says that the OP _is_ trying to parse JSON: "Each one represents a key in a JSON file I want to get the values out of to transform into CSV". So `json.load` or `json.loads` can be used to load that JSON data into a Python object which can then be tested against the strings in the `required_fields` list. – PM 2Ring Jul 08 '16 at 07:59
  • @whoisearth: It would help if you could add a short example of some typical JSON data that you want your program to convert to CSV. And I guess you should also tell us what fields you want that CSV to contain. – PM 2Ring Jul 08 '16 at 08:04
  • @PM2Ring He already *did* parse the JSON, it's `server_list`. He can't parse the *lookup via keys* to the JSON file as JSON, because *json doesn't have a concept for that*. It's just data, not statements. If `required_fields` were a plain JSON containing just the keys, it'd work - but it is not. – MisterMiyagi Jul 08 '16 at 08:05
  • @PM2Ring, have a look at the new answer, it works without `eval`. @whoisearth does this work with the constraints of your formatting? – MisterMiyagi Jul 08 '16 at 08:09

2 Answers2

3

This is an alternative approach. Note that it works on the assumption that your content is always of the form server[<key>][<key>][...].

import ast

def parse_fields(field):
    field = field[6:]  # remove leading "server"
    field = field[1:-1]  # remove leading/trailing "[" and "]"
    fields = field.split('][')  # split at intermediate "]["
    return [ast.literal_eval(field) for field in fields]  # parse keys, e.g. 'foobar' to str foobar

Then you can just use the keys directly:

for server in server_list:
  for item in required_fields:
    value = server
    for key in parse_fields(field):
        value = value[key]
    print item, value

Of course, you can also write parse_fields shorter:

def parse_fields(fields):
  return [ast.literal_eval(field) for field in fields[7:-1].split('][')]
MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119
-1

What you are looking for is eval:

for server in server_list:
  for item in required_fields:
    print(eval(item))

eval will "run" a string as if it were plain code. For example,

eval('print("foo")')
print("foo")

both give the same result.

Mandatory Note: Please don't use eval if the source of the code to execute is potentially untrusted. See the other answer in this case, or if you are unsure.

MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119
  • 2
    I know you've added that Mandatory Note, but `eval` and `exec` should generally be avoided because they can be a security risk. For those interested in learning more, please see [Eval really is dangerous](http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html) by SO veteran Ned Batchelder. – PM 2Ring Jul 07 '16 at 15:23
  • 2
    @whoisearth The core of SO is to provide expert advice to problems. If your question is something like, "How do I jump off a building with no parachute and no airbag to land on?" then *experts* are going to warn you that it's a bad idea and you'll probably die. If you *know* it's a bad idea and you'll probably die but you still want to take precautions and build a ramp and maybe drop off the building with a skateboard which is super dangerous and still nobody should ever do and you say that's your goal we'll still help. But if you just want to get to the ground floor, use the elevator. – Wayne Werner Jul 07 '16 at 15:50
  • 1
    @WayneWerner - agree 100%. which is why I find it funny that this solution was negatively voted against. It's the "right" solution for what I asked. – whoisearth Jul 07 '16 at 15:52
  • @MisterMiyagi I'm not interested in debating the merits of `eval`. I downvoted you because I'm not a big fan of taking OPs at face value when they come in with a strange problem that they shouldn't be encountering in the first place, like having stringified data that apparently needs to be eval'd. Whatever is generating that data needs to be fixed. Instead we're wasting StackOverflow's resources and theirs by "fixing" the issues resulting from that. That's not how I fix my code or my company's, and it's not how I recommend others do it. – Two-Bit Alchemist Jul 08 '16 at 13:36