1

I am writing a a REST API in python3 using flask and I have struggled to find a way to return a dict as json while maintaining the order of the keys. I am using an OrderedDict because obviously the built in dictionary does not preserve order of elements.

I have a method that looks like this:

@app.route('/foobar', methods=['GET'])
def foobar()
    data = [OrderedDict([("a",1),
        ("b",2),
        ("c",3)])]
    return jsonify(data),200

And here is an example of the output I could get:

[{"b":2,"c":3,"a":1}]

This is what I want to get:

[{"a":1,"b":2,"c":3}]

How can I return JSON in the order that its defined in the ordered dict?

Edit: This is not a duplicate because the linked post is only for a dictionary I need this to work for a list of dictionaries

bs7280
  • 1,074
  • 3
  • 18
  • 32

2 Answers2

-1

According to RFC7159, JavaScript Object Notation (JSON) is a text format for the serialization of structured data. It is derived from the object literals of JavaScript, as defined in the ECMAScript Programming Language Standard, Third Edition [ECMA-262].

An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array.

An array is an ordered sequence of zero or more values.

For make order for your json you can use this:

@app.route('/')
def foobar():
    data = OrderedDict([("a",1), ("z",2), ("c",3)])
    return json.dumps([data])

Output

[{"a": 1, "z": 2, "c": 3}]

If sort_keys is true (default: False), then the output of dictionaries will be sorted by key. For sorting, You can change your code to this:

@app.route('/foobar', methods=['GET'])
def foobar()
    data = [OrderedDict([("a",1),
        ("z",2),
        ("c",3)])]
    return json.dumps(data, sort_keys=True)

Output

[{"a": 1, "c": 3, "z": 2}]

spazm
  • 4,399
  • 31
  • 30
RaminNietzsche
  • 2,683
  • 1
  • 20
  • 34
-2

Your problem is that the OrderedDict keeps insertion order for newly added/modified key/value pairs.

It's all down to how you get the key/values in the dictionary.

If you pass standard **kwargs, you will fail.

If the elements are passed as an iterable (as seen in your example) or later inserted, the order will be preserverd.

Standard kwargs

d = OrderedDict(a=1, b=2, c=3)
data = [d]
print(json.dumps(data))

Output:

[{"a": 1, "c": 3, "b": 2}]

Wrong order.

But with an iterable

d = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
data = [d]
print(json.dumps(data))

Output:

[{"a": 1, "b": 2, "c": 3}]

Order has been preserved.

Manual insertion

d = OrderedDict()
d['a'] = 1
d['b'] = 2
d['c'] = 3
data = [d]
print(json.dumps(data))

Output:

[{"a": 1, "b": 2, "c": 3}]

And order has been preserved again

mementum
  • 3,153
  • 13
  • 20