11

I have a piece of information like so:

[{"city": "Beverly Hills", "state": "", "postal_code": "", "address": "Some Address", "country": "USA"}, {"city": "New York", "state": "NY", "postal_code": "", "address": "P.O. BOX 52404", "country": "USA"}]

When I do type() it shows as <class 'str'>.

How do I get this information from a string to a list of dictionaries in Python 3?

I've tried literal_eval and got an error malformed node or string:, so I am not sure what the best way to do this is.'

EDIT

Here is an example that should be reproducible:

mydata = {'programs': '["France"]', 'ids': '[]', 'citizenships': '[]', 'nationalities': '["FR"]', 'places_of_birth': '[]', 'dates_of_birth': '["1973-03-25"]', 'addresses': '[{"state": null, "postal_code": null, "address": null, "city": null, "country": "FR"}]'}
for key,value in mydata.items():
    if type(value) is str:
        result = literal_eval(value)
        print("value 1: ", value)
        print("value type 2:", type(value))
        print("result 3: ", result)
        print("result  4: ", type(result))
        for item in result:
            print("item in result 5:", item)
            print("type of item in result 6:", type(item))

Here is the error:

File "server.py", line 137, in insert_in_db result = literal_eval(value)
File "/Users/user/anaconda3/envs/apicaller/lib/python3.5/ast.py", line 84, in literal_eval return _convert(node_or_string)
File "/Users/user/anaconda3/envs/apicaller/lib/python3.5/ast.py", line 57, in _convert return list(map(_convert, node.elts))
File "/Users/user/anaconda3/envs/apicaller/lib/python3.5/ast.py", line 62, in _convert in zip(node.keys, node.values))
File "/Users/user/anaconda3/envs/apicaller/lib/python3.5/ast.py", line 61, in return dict((_convert(k), _convert(v)) for k, v
File "/Users/user/anaconda3/envs/apicaller/lib/python3.5/ast.py", line 83, in _convert raise ValueError('malformed node or string: ' + repr(node)) ValueError: malformed node or string: <_ast.Name object at 0x109baae48>

Maybe I am missing a step in between to check for null values? I seem to get the error on the eval line 137. I got the idea to use ast.literal_eval from that stack overflow comment mentioned below.

Is it more of a data issue than with the way I am handling it? I am not very familiar with Python so I am most likely missing something.

M. Eriksson
  • 13,450
  • 4
  • 29
  • 40
unseen_damage
  • 1,346
  • 1
  • 14
  • 32

5 Answers5

20
import json

data = json.loads(<your_string>)
dimmg
  • 3,316
  • 2
  • 20
  • 29
  • 3
    The user's string (if it's as shown) should work with literal_eval as well. Whatever the problem is, it's probably not that the issue is that it's valid JSON but not valid Python. Are you proposing that it's a null/None issue or something? – DSM Nov 10 '17 at 21:39
8

I know i'm answering pretty late but hope it is helpful for other folks:

you can use: pip install pyyaml import yaml

x = '[{"city": "Beverly Hills", "state": "", "postal_code": "", "address": "Some Address", "country": "USA"}, {"city": "New York", "state": "NY", "postal_code": "", "address": "P.O. BOX 52404", "country": "USA"}]'

x = yaml.load(x)

Now string has been converted to list of dictionaries.

Deepak Joshi
  • 329
  • 3
  • 4
  • 1
    PyYAML's `yaml.load()` is documented to be potentially unsafe. It is also not necessary to use it here, so there is no excuse for suggesting to use it. – Anthon Sep 28 '18 at 11:31
  • 2
    **This worked for me to get a list of dicts from a str.** `yaml.load` has been deprecated because it could be easily exploited (as @Anthon commented). Now a Loader has to be specified. For example `yaml.load(x, Loader=yaml.BaseLoader)` Read https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation for more information. – daco Jan 24 '20 at 08:54
4

You can use json module, if you your informating is of type string

import json

data = json.loads(<your_string>)

for element in data:
    for key, value in element.items():
        print("{}: {}".format(key, value))
lambda
  • 407
  • 1
  • 5
  • 18
0

That is of type list?

You should be able to set a variable to that list and it should work. However, if the data is a literal string you could do this:

import json
test = json.loads('[{"city": "Beverly Hills", "state": "", "postal_code": "", "address": "Some Address", "country": "USA"}, {"city": "New York", "state": "NY", "postal_code": "", "address": "P.O. BOX 52404", "country": "USA"}]')

print(type(test))
-><type 'list'>
spitfire21
  • 103
  • 4
0

There is JSON encoder and decoder. You can have a look at here for documentation. json.loads(<to_be_convert_string>)

Python3 example and its output

import json
data = json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
print(data) # ['foo', {'bar': ['baz', None, 1.0, 2]}]
print(type(data)) # <class 'list'>
print(type(data[0])) # <class 'str'>
print(type(data[1])) # <class 'dict'>

You can have more examples at this link

Shubhank Gupta
  • 705
  • 2
  • 10
  • 27