0

I have a script which processes data returned from a web API. The data returned is a string representation of a list of dictionaries.

I know about ast.literal_eval() to convert the string representation of the dictionaries into real ones.

The data looks like this (Reminder: those are strings, not dicts):

new = [{"id": "L0", "tags": null, "disable": false},
       {"id": "L1", "tags": null, "disable": false},
       {"id": "L2", "tags": null, "disable": false}]

Because 'null' and 'false' are not enclosed in quotes, ast.literal_eval() fails with an error. If I manually add quotes to null and false above, it works perfectly.

I was trying to iterate through the strings and modify the substrings null and false to "null" and "false" with this, but it does nothing:

for i in new:
    i.replace("null", "\"null\"")
    i.replace("false", "\"false\"")

How do I modify those substrings to add enclosing quotes? If possible I would prefer to modify the existing list (new[]) instead of creating a new one, but if I have to create a new one to get it to work, then that's what I will do.

MarkS
  • 1,455
  • 2
  • 21
  • 36
  • I'm assuming you mean `None` and `False`? – Easton Bornemeier Jul 12 '18 at 14:56
  • **@MarkS**, if **new** is a string then you a little correct with your approach. Do not use for loop. Just 2 lines are enough. Also do not forget to re assign the returned value after replace operation. Note that strings are immutable in Python. For example, `i = i.replace("null", "\"null\"")` – hygull Jul 12 '18 at 16:12

2 Answers2

1

@MarkS, if new is a string representation of the list of dictionaries then you can also try the below code.

from ast import literal_eval

new = '''[{"id": "L0", "tags": null, "disable": false},
       {"id": "L1", "tags": null, "disable": false},
       {"id": "L2", "tags": null, "disable": false}]'''

new = new.replace('false', '\"false\"')
new = new.replace('null', '\"null\"')

print(new)
"""
    [{"id": "L0", "tags": "null", "disable": "false"},
       {"id": "L1", "tags": "null", "disable": "false"},
       {"id": "L2", "tags": "null", "disable": "false"}]
"""

print(literal_eval(new))
"""
    [{'id': 'L0', 'tags': 'null', 'disable': 'false'}, {'id': 'L1', 'tags': 'null', 'disable': 'false'}, {'id': 'L2', 'tags': 'null', 'disable': 'false'}]
"""
hygull
  • 8,464
  • 2
  • 43
  • 52
  • I think my question was a bit unclear. The list is a list, but the values of the list are strings that look like dicts. That's why I stated I was trying for i in new: I am iterating over each string in the actual list new. – MarkS Jul 12 '18 at 16:11
0

You can modify the data just before running ast.literal_eval(), possibly with re module:

import re
from ast import literal_eval
from pprint import pprint

s = """new = [{"id": "L0", "tags": null, "disable": false},
       {"id": "L1", "tags": null, "disable": false},
       {"id": "L2", "tags": null, "disable": false}]"""

s = re.sub('null', '"null"', s)
s = re.sub('false', '"false"', s)
s = re.sub('new\s*=\s*', '', s)

new = literal_eval(s)
pprint(new)

Output:

[{'disable': 'false', 'id': 'L0', 'tags': 'null'},
 {'disable': 'false', 'id': 'L1', 'tags': 'null'},
 {'disable': 'false', 'id': 'L2', 'tags': 'null'}]
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
  • I think my question was a bit unclear. The list is a list, but the values of the list are strings that look like dicts. That's why I stated I was trying for i in new: I am iterating over each string in the actual list new. – MarkS Jul 12 '18 at 16:10
  • @MarkS You need to provide then raw input and expected output in your question. – Andrej Kesely Jul 12 '18 at 16:12
  • 1
    kesley, after adjusting my program a bit to accommodate the solution you provided, I got it to work they way I want. I now successfully create a list of dicts. Thanks. – MarkS Jul 12 '18 at 16:21