AlanObject
AlanObject

Reputation: 9943

The jsonpickle converts my dictionary keys from numbers to strings

I was trying to serialize my objects in a way that I could read them in the external form and found jsonpickle. But it turns out that it converts my dictionary keys from integers to strings.

I noticed this thread on the problem using just the JSON package but I was hoping that jsonpickle would fix the problem. Are there any known workarounds? Alternatively is there a better text-mode serialization format to use for Python?

Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 23 2015, 02:52:03) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
>>> a={}
>>> a[11]="eleventy"
>>> a[22]="twice that"
>>> a
{11: 'eleventy', 22: 'twice that'}
>>> import jsonpickle
>>> jstring=jsonpickle.encode(a)
>>> jstring
'{"22": "twice that", "11": "eleventy"}'
>>> b=jsonpickle.decode(jstring)
>>> b
{'22': 'twice that', '11': 'eleventy'}
>>> 

Update: For short term my work around is to have parallel save functions -- one to pickle and one to jsonpickle. Since my objects are complex (circular references) I can't get away with something that can't handle that. My original requirement was to have a format that I could read in a text editor so I could detect problems with the logic so as long as regular pickel is reliable (it is) than that will do me for now. Someday I might want to have some other non-Python software eat this file so I would like to find a usable solution. XML format? The Python community doesn't seem to be that interested in serializing to XML. At least I haven't found a package that works as easily as pickle/jsonpickle does.

Upvotes: 5

Views: 3561

Answers (4)

brunovianarezende
brunovianarezende

Reputation: 866

In jsonpickle you can use the 'keys' argument to save keys without coercing them to string.

To encode, do:

jsonpickle.encode(your_object, keys=True)

and to decode:

jsonpickle.decode(the_encoded_object, keys=True)

Upvotes: 5

laike9m
laike9m

Reputation: 19318

enter image description here

This is the JSON object definition from http://json.org. So basically all keys MUST be string, so your int key will be converted to string when converting object to JSON object. Nothing else.

You don't have to use jsonpickle if all you need is string representation.

>>> a={}
>>> a[11]="eleventy"
>>> a[22]="twice that"
>>> str(a)
"{11: 'eleventy', 22: 'twice that'}"

Upvotes: 1

Stefan Pochmann
Stefan Pochmann

Reputation: 28596

You could use repr for small things or pprint in general:

>>> a = {i: i for i in range(20)}
>>> import pprint
>>> pprint.pprint(a)
{0: 0,
 1: 1,
 2: 2,
 3: 3,
 4: 4,
 5: 5,
 6: 6,
 7: 7,
 8: 8,
 9: 9,
 10: 10,
 11: 11,
 12: 12,
 13: 13,
 14: 14,
 15: 15,
 16: 16,
 17: 17,
 18: 18,
 19: 19}

You can also give pprint a stream to write into:

with open('mydata.txt', 'w') as f:
    pprint.pprint(a, f)

And you can read that back like this:

import ast
with open('mydata.txt') as f:
    b = ast.literal_eval(f.read())

Upvotes: 1

wouter bolsterlee
wouter bolsterlee

Reputation: 4037

This is because the JSON format (http://json.org/) requires all keys in an object (dict keys in python) to be strings.

Though not text based, MessagePack allows integer mapping keys:

>>> import msgpack
>>> type(msgpack.unpackb(msgpack.packb({12: 23})).keys()[0])
<type 'int'>

Upvotes: 1

Related Questions