JSON String conversion to Dict - python

I'm having trouble converting the below JSON string to type dict. json.loads throws an error because of the two sets of squiggles: {}, {}
test = '{"124074": "0.0944", "124111": "0.0809", "124194": "0.0788"}, {"128213": "0.39", "129043": "0.458", "129054": "0.378"}'
Any thoughts on how I fix this? I need to be able to convert to dict so I can iterate through the keys. Should the JSON string be represented in a different way?

Based on the comment from #rv.kvetch, one can get the following result
>>> test = '{"124074": "0.0944", "124111": "0.0809", "124194": "0.0788"}, {"128213": "0.39", "129043": "0.458", "129054": "0.378"}'
>>> dicts = json.loads(f'[{test}]')
>>> dicts
[{'124074': '0.0944', '124111': '0.0809', '124194': '0.0788'}, {'128213': '0.39', '129043': '0.458', '129054': '0.378'}]
>>> dicts[0]
{'124074': '0.0944', '124111': '0.0809', '124194': '0.0788'}
>>> type(dicts[0])
<class 'dict'>
essentially a list of dicts is created instead of a single dict.

Related

Convert String of List to List in Python

I need to convert a string of list to List in Python. I have seen many of the similar questions but none of them works in this case.
I am passing some values through PostMan.
The key passing as a form data
Key = controls
value = [CR1,CR2]
I am fetching the data like this
c_list = self._kwargs['data'].get('controls', [])
print(c-list)
print(type(c-list))
I am getting the following o/p
[CC-2,CC-3]
<class 'str'>
But I need to get it as a list so I have tried the following method
import ast
c_list = self._kwargs['data'].get('controls', [])
res = ast.literal_eval(c_list)
But I am getting the following Error
malformed node or string: <_ast.Name object at 0x7f82966942b0>
You could simply do the following: strip the brackets and split on the commas
>>> s = "[CC-2,CC-3]"
>>> s.strip('[]').split(',')
['CC-2', 'CC-3']

remove quotes from a json file using python

the dataframe 'dataset' is automatically generated by PowerBI here is the result of my dataset.head(10).to_clipboard(sep=',', index=False)
coordinates,status
"[143.4865219,-34.7560602]",not started
"[143.4865241,-34.7561332]",not started
"[143.4865264,-34.7562088]",not started
"[143.4865286,-34.7562818]",not started
"[143.4865305,-34.7563453]",not started
"[143.4865327,-34.7564183]",not started
"[143.486535,-34.756494]",not started
"[143.4865371,-34.756567]",not started
"[143.486539,-34.7566304]",not started
"[143.4865412,-34.7567034]",not started
then to get the json
i do this data=dataset.to_json(orient='records')
which give me this results
[{"coordinates":"[143.4865219,-34.7560602]","status":"not started"},{"coordinates":"[143.4865241,-34.7561332]","status":"not started"},
how i get this instead , no quotes on the coordinates values
[{"coordinates":[143.4865219,-34.7560602],"status":"not started"},{"coordinates":[143.4865241,-34.7561332],"status":"not started"},
edit
print(type(data))
<class 'str'>
You could use ast.literal_eval:
Safely evaluate an expression node or a string containing a Python
literal or container display. The string or node provided may only
consist of the following Python literal structures: strings, bytes,
numbers, tuples, lists, dicts, sets, booleans, and None.
This can be used for safely evaluating strings containing Python
values from untrusted sources without the need to parse the values
oneself.[...]
Your data seems to be a string, and not a list as Python would print it (it uses single quotes by default, the double quotes in your data seem to indicate that it is a string, ready to be saved in a json file for example). So, you have to convert it first to a Python object with json.loads:
from ast import literal_eval
import json
data = """[{"coordinates":"[143.4865219,-34.7560602]","status":"not started"},{"coordinates":"[143.4865241,-34.7561332]","status":"not started"}]"""
data = json.loads(data)
for d in data:
d['coordinates'] = literal_eval(d['coordinates'])
print(data)
# [{'coordinates': [143.4865219, -34.7560602], 'status': 'not started'}, {'coordinates': [143.4865241, -34.7561332], 'status': 'not started'}]
import json
s = '[{"coordinates":"[143.4865219,-34.7560602]","status":"not started"},{"coordinates":"[143.4865241,-34.7561332]","status":"not started"}]'
d = json.loads(s)
d[0]['coordinates'] = json.loads(d[0]['coordinates'])
Applying this concept to every value can be done as in
for dic in d:
for key, value in dic.items():
try:
temp = json.loads(value)
if isinstance(temp, list):
dic[key] = temp
except Exception:
pass
or if you are sure there will be a coordinates key in ever dictionary
and that key having a "list" value
for dic in d: dic['coordinates'] = json.loads(dic['coordinates'])
simply u can use eval function.
new =[]
l = '[{"coordinates":"[143.4865219,-34.7560602]","status":"not started"},{"coordinates":"[143.4865241,-34.7561332]","status":"not started"}]'
l=eval(l)
for each_element in l:
temp={}
for k,v in each_element.items():
if k =='coordinates' :
temp[k]=eval(v)
else:
temp[k]=v
new.append(temp)
print(temp)

Python: Usage of anonymous list within dict of other values?

I am asked to generate and also later read back a json object which looks like:
{"name":"somename",
[{"id":123,"key1":"anydata"},
{"id":345,"key1":"x","key3":"yz"}]}
Normally, I would use a python dict and convert it to/from json. Here however is the problem, that both, list and sub-dict are anonymous.
I think it is not possible to make a dict like this, is it?
This is not a valid json object but you can just add a key for the list part. Like:
{"name":"somename","value" : [{"id":123,"key1":"anydata"},{"id":345,"key1":"x","key3":"yz"}]}
Now this is a valid json string.
>>> a = ast.literal_eval('{"name":"somename","value" : [{"id":123,"key1":"anydata"},{"id":345,"key1":"x","key3":"yz"}]}')
>>> print(a['name'])
>>> 'somename'
>>> print(a['value'][0]['id'])
>>> 123
For a variable list its is as simple as:
anon_list = [{"id":123,"key1":"anydata"},{"id":345,"key1":"x","key3":"yz"}]
a = {"name":"somename","value" : anon_list}
>>> print(a['name'])
>>> 'somename'
>>> print(a['value'][0]['id'])
>>> 123

How can I parse a dictionary string?

I am trying to convert a string to a dictionary with dict function, like this
import json
p = "{'id':'12589456'}"
d = dict(p)
print d['id']
But I get the following error
ValueError: dictionary update sequence element #0 has length 1; 2 is required
Why does it fail? How can I fix this?
What you have is a string, but dict function can only iterate over tuples (key-value pairs) to construct a dictionary. See the examples given in the dict's documentation.
In this particular case, you can use ast.literal_eval to convert the string to the corresponding dict object, like this
>>> p = "{'id':'12589456'}"
>>> from ast import literal_eval
>>> d = literal_eval(p)
>>> d['id']
'12589456'
Since p is a string containing JSON (ish), you have to load it first to get back a Python dictionary. Then you can access items within it:
p = '{"id":"12589456"}'
d = json.loads(p)
print d["id"]
However, note that the value in p is not actually JSON; JSON demands (and the Python json module enforces) that strings are quoted with double-quotes, not single quotes. I've updated it in my example here, but depending on where you got your example from, you might have more to do.

JSON encoding for dict of dicts

Let us say I have a custom data structure comprising of primitive dicts. I need to serialize this using JSON. My structure is as follows:
path_list_dict = {(node1, node2 .. nodeN): (float1, float2, float3)}
So this is keyed with a tuple and the value is a tuple of three values. Each node element in the key is a custom class object with a _str_ method written for it. The wrapper dict which identifies each dict entry in path_list_dict with a key is as follows:
path_options_dict = {‘Path1’: {(node1, node2 .. nodeN): (float1, float2, float3)}, ‘Path2’: {(nodeA1, nodeA2 .. nodeAN): (floatA1, floatA2, floatA3)} }
and so on.
When I try to serialize this using JSON, of course I run into a TypeError because the inner dict has tuples as keys and values and a dict needs to have keys as strings to be serialized. This can be easily taken care of for me by inserting into the dict as the str(tuple) representation instead of just the native tuple.
What I am concerned about is that when I receive it and unpack the values, I am going to have all strings at the receiving end. The key tuple of the inner dict that consists of custom class elements is now represented as a str. Will I be able to recover the embedded data? Or is these some other way to do this better?
For more clarity, I am using this JSON tutorial as reference.
You have several options:
Serialize with a custom key prefix that you can pick out and unserialize again:
tuple_key = '__tuple__({})'.format(','.join(key))
would produce '__tuple__(node1,node2,nodeN)' as a key, which you could parse back into a tuple on the other side:
if key.startswith('__tuple__('):
key = tuple(key[10:-1].split(','))
Demo:
>>> key = ('node1', 'node2', 'node3')
>>> '__tuple__({})'.format(','.join(key))
'__tuple__(node1,node2,node3)'
>>> mapped_key = '__tuple__({})'.format(','.join(key))
>>> tuple(mapped_key[10:-1].split(','))
('node1', 'node2', 'node3')
Don't use dictionaries, use a list of lists:
{'Path': [[[node1, node2 .. nodeN], [float1, float2, float3]], [...]]}
You can build such a list simply from the dict.items() result:
>>> json.dumps({(1, 2, 3): ('foo', 'bar')}.items())
'[[[1, 2, 3], ["foo", "bar"]]]'
and when decoding, feed the whole thing back into dict() while mapping each key-value list to tuples:
>>> dict(map(tuple, kv) for kv in json.loads('[[[1, 2, 3], ["foo", "bar"]]]'))
{(1, 2, 3): (u'foo', u'bar')}
The latter approach is more suitable for custom classes as well, as the JSONEncoder.default() method will still be handed these custom objects for you to serialize back to a suitable dictionary object, which gives means that a suitable object_hook passed to JSONDecoder() a chance to return fully deserialized custom objects again for those.

Categories