1

I need to show an output like below as a result of a webservice call

{
  "predictions": [
    {
      "id": 18009,
      "cuisine": "italian",
      "probability": 0.17846838753494407
    },
    {
      "id": 28583,
      "cuisine": "italian",
      "probability": 0.1918703125538735
    }
  ]
}

I have the below code to create the object:

    json_data = []
    for i in range (0, len(predicted_labels)):
        data = {}
        data['id'] = int(test['id'][i])
        data['cuisine'] = categoricalTransformer[predicted_labels[i]]
        item = predicted_probability[i]
        data['probability'] = item[predicted_labels[i]]
        json_data.append(data)
    json_return = {"predictions":json_data}
    return jsonify(json_return)

which reorders the key alphabetically as shown below.

{
  "predictions": [
    {
      "cuisine": "italian",
      "id": 18009,
      "probability": 0.17846838753494407
    },
    {
      "cuisine": "italian",
      "id": 28583,
      "probability": 0.1918703125538735
    }
  ]
}

What should I do?

nad
  • 2,640
  • 11
  • 55
  • 96

2 Answers2

4

Rebuild your new dictionary with a collections.defaultdict(), and append ordered dictionaries with a collections.OrderedDict():

from collections import OrderedDict
from collections import defaultdict
from json import dumps

data = {
    "predictions": [
        {"id": 18009, "cuisine": "italian", "probability": 0.17846838753494407},
        {"id": 28583, "cuisine": "italian", "probability": 0.1918703125538735},
    ]
}

key_order = ["id", "cuisine", "probability"]

result = defaultdict(list)
for dic in data["predictions"]:
    ordered = OrderedDict((key, dic.get(key)) for key in key_order)
    result["predictions"].append(ordered)

print(dumps(result))
# {"predictions": [{"id": 18009, "cuisine": "italian", "probability": 0.17846838753494407}, {"id": 28583, "cuisine": "italian", "probability": 0.1918703125538735}]}

json.dumps() here serializes the dictionary into a JSON formatted string.

Note: If you are using Python3.6+, you can use normal dictionaries instead of OrderedDict(), since insertion order of keys is remembered. However, in 3.6 it is an implementation feature, whereas in 3.7 it is a language feature. You read more about this at Are dictionaries ordered in Python 3.6+?.

You can probably rely on this feature for applications that have a minimum requirement of Python3.6. Furthermore, its probably safer to user OrderedDict() anyways, so your code can be backwards compatible for all python versions.

RoadRunner
  • 25,803
  • 6
  • 42
  • 75
  • 2
    Although you are correct that Python 3.6+ remembers insertion order, this behaviour is a side-effect of an implementation change and should not be relied on. For more future-proof code and greater reusability, `OrderedDict` should be used. – Grismar Jan 07 '19 at 03:10
  • @Grismar Yes thats a very good point, cheers. – RoadRunner Jan 07 '19 at 03:14
  • 2
    @Grismar This is correct for 3.6 only. Since Python 3.7 it is a documented feature. Still backward compatibility should be considered. – Klaus D. Jan 07 '19 at 04:01
0

You can look into Ordered Dictionary. It remembers the insertion order, and you would be able to organise your json via this collection this way.

Example:

datadict = {'a':'a', 'c':'c', 'b':'b'}
import collections

print (collections.OrderedDict(datadict))
#OrderedDict([('a':'a'), ('c':'c'), ('b':'b')])

x = collections.OrderedDict(datadict)
print (dict(x))
#{'a':'a', 'c':'c', 'b':'b'}

print (x == datadict)
#True


print (collections.OrderedDict(sorted(datadict.items(), key=lambda t:t[0])))
#OrderedDict([('a':'a'), ('b':'b'), ('c':'c')])

z = collections.OrderedDict(sorted(datadict.items(), key=lambda t:t[0]))
print (dict(z))
#{'a':'a', 'b':'b', 'c':'c'}

print (z == datadict)
#True

Using this, you can convert your json_return dict object into an OrderedDict with your desired insertion order and then return that OrderedDict object or convert it back into a dict and return that dict

ycx
  • 3,155
  • 3
  • 14
  • 26