Reputation:
I'm trying to serialize my Python objects into JSON using json.dumps
. If you serialize a dict
using json.dumps
it will obviously be serialized as a JSON dictionary {..}
; if you serialize a list
or a tuple
, it will be a JSON array.
I want to know if there's any way to easily serialize a Python dict
as a JSON list
, if possible. By if possible, I mean if the keys start at 0 and are sequenced, for example:
{0:'data',1:'data',2:'data}
The above would be serialized into JSON as: '{"0": "data", "1": "data", "2": "data"}'
, but I would like it to be serialized as ['data','data','data']
since the keys start at 0 and are sequenced.
My reasoning for this is because I have lots of JSON data that is serialized from PHP, where in PHP arrays have keys and if the keys are sequenced as described above, PHP's json.encode
uses arrays, if they are keyed in any other manner, they are serialized as JSON dictionaries. I want my JSON serializations to match for both my PHP and Python code. Unfortunately, changing the PHP code isn't an option in my case.
Any suggestions? The only solution I have found is to write my own function to go through and verify each python dictionary and see if it can first be converted to a list
before json.dumps
.
EDIT: This object that I'm serializing could be a list
or a dict
, as well, it could have additional dicts inside of it, and lists, and so on (nesting). I'm wondering if there's any 'simple' way to do this, otherwise I believe I can write a recursive solution myself. But it's always better to use existing code to avoid more bugs.
Upvotes: 5
Views: 10279
Reputation: 80436
I don't know of a solution without recursion... Although you can call your converter from inside the encode
method of your custom Encoder
, it would just add unnecessary complexity.
In [1]: import json
In [2]: d = {"0": "data0", "1": "data1", "2": {"0": "data0", "1": "data1", "2": "data2"}}
In [3]: def convert(obj):
...: if isinstance(obj, (list, tuple)):
...: return [convert(i) for i in obj]
...: elif isinstance(obj, dict):
...: _, values = zip(*sorted(obj.items()))
...: return convert(values)
...: return obj
In [4]: json.dumps(convert(d))
Out[4]: '["data0", "data1", ["data0", "data1", "data2"]]'
Upvotes: 2
Reputation: 11814
Normally you could subclass json.JSONEncoder
to create your own custom JSON serializer, but that won't allow you to override built-in object types.
If you create your own custom dictlist
object (or whatever you want to call it) that doesn't extend dict
or list
you should be able to override the JSONEncoder.default
method to create your own custom JSON serializer.
Regardless of whether you create a custom JSON serializer or recursively replace your special dict
instances with lists you will need a function that accepts a dict
and returns either a list
or a dict
as appropriate.
Here's one implementation:
def convert_to_list(obj):
obj_list = []
for i in range(len(obj)):
if i not in obj:
return obj # Return original dict if not an ordered list
obj_list.append(obj[i])
return obj_list
Upvotes: 0
Reputation: 298532
You could convert the dictionary into a list of tuples and then sort it, as dictionary items won't necessarily come out in the order than you want them to:
items = sorted(d.items(), key=lambda item: item[0])
values = [item[1] for item in items]
json_dict = json.dumps(values)
Upvotes: 2