4

I create objects (using tkinter widgets) that I wish to save in a JSON or XML file, so that I can recover them after startup.

from Tkinter import *

class Texte:
    def __init__(self, ax, ay, txt):
        self.entry = Entry(root,bd=0,font=("Purisa",int(15)))
        self.entry.insert(0, txt)
        self.x = ax
        self.y = ay 
        self.entry.place(x=self.x,y=self.y)

root = Tk()

a = Texte(10, 20, 'blah')
b = Texte(20, 70, 'blah2')

# here the user will modify the entries' x, y, txt, etc.

L = [a,b]

# here save the list L (containing the Texte objects) into a JSON file or XML so that I can recover them after restart 

root.mainloop()

How can save and restore these objects with JSON or XML ?

(I'm a bit lost with http://docs.python.org/2/library/json.html right now.)

Basj
  • 41,386
  • 99
  • 383
  • 673

3 Answers3

6

It's mentioned in the docs, use json.dump.

Example of use:

import json

data = {'a':1, 'b':2}
with open('my_json.txt', 'w') as fp:
    json.dump(data, fp)

In your case, you can't convert the object itself to a json format. Save the information only:

data = {'a':(10, 20, 'blah'), 'b':(20, 70, 'blah2')
with open('my_json.txt', 'w') as fp:
     json.dump(data, fp)

And when you load it back:

with open('my_json.txt') as fp:
    data = json.loads(fp)
    a = Texte(*data['a'])
    b = Texte(*data['b'])
aIKid
  • 26,968
  • 4
  • 39
  • 65
  • Is it so simple? (It seems that I need a `write()` for my object, do you have a clue of what it could be in my example with Entry widgets?) – Basj Dec 12 '13 at 09:58
  • No, you don't need to write it. `json.dump` will automatically export what you need to the specified file. – aIKid Dec 12 '13 at 10:14
  • I tried to paste your code at the end of mine and I get : `AttributeError: 'str' object has no attribute 'write'` – Basj Dec 12 '13 at 10:17
  • Oh whoops, i was supposed to pass the file object. Sorry! Updated. – aIKid Dec 12 '13 at 10:19
  • It runs now, but the resulting .txt file only contains `{"a": 1, "b": 2}` as text, and not the objects a and b's contents – Basj Dec 12 '13 at 10:23
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/43027/discussion-between-basj-and-aikid) – Basj Dec 12 '13 at 10:27
3

If you never modify these objects outside of your Application why the requirement for JSON or XML? If you don't change your data outside of your application you can use the pickle Module to serialize and deserialize the object into either binary data or a ASCII string and save these.

For details see: http://docs.python.org/2/library/pickle.html

There is also a 3rd party library which enables storage of classes as JSON. http://jsonpickle.github.io/

I haven't used it yet myself though so not sure how human readable the output is, but if all you want to do is store it as file and reload it after a application restart I don't see any advantage of JSON/XML over using Pickle.

Edit: As others pointed out you can use cPickle over pickle for better performance. The Algorithm is the same so you use them the exact same way.

1

Please see update: json is simplejson.

json.dump(for file export) and json.dumps(for string export) can be very useful if you have a simple object. However, if you need to save a more complex data structure like a dictionary filled with dictionaries {'a':{...}, 'b':2} json from the standard library struggles.

For such cases a tool like simplejson can be useful. http://simplejson.readthedocs.org/en/latest/

>>> import simplejson as json
>>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
'["foo", {"bar": ["baz", null, 1.0, 2]}]'
>>> print(json.dumps("\"foo\bar"))
"\"foo\bar"
>>> print(json.dumps(u'\u1234'))
"\u1234"

As you need to save a complex list L to json - I would go with simplejson. Something like:

import simplejson as json
with open('Texte.json', 'w') as texte_file:
    json.dump(L, texte_file)`

Update: simplejson is json from the standard library (added in 2.6 to the standard library). For more details see: What are the differences between json and simplejson Python modules?.

Community
  • 1
  • 1
Jon
  • 11,356
  • 5
  • 40
  • 74
  • Hum, I think I am unable to decide if `json` or `simplejson` would be more adapted. How would you save the object in my example (do I require a `write()`) method in my class? – Basj Dec 12 '13 at 10:00
  • woud you have a hint with my simple object example (an object containing a widget, a x, a y, a string) ? – Basj Dec 12 '13 at 10:08
  • 1
    I edited my example for your cause. Please post a comment if you need more details. – Jon Dec 12 '13 at 10:08
  • 1
    Where did you find out that the standard `json` library struggles when dealing with nested dictionaries? – aIKid Dec 12 '13 at 10:16
  • @aIKid: Thanks for your advice (+1). `simplejson` is `json` - see http://stackoverflow.com/questions/712791/what-are-the-differences-between-json-and-simplejson-python-modules – Jon Dec 12 '13 at 10:26
  • here same problem : `TypeError: <__main__.Texte instance at 0x02463918> is not JSON serializable` – Basj Dec 12 '13 at 10:34
  • The default json encoder can't deal with custom classes. You can either transform your class into a simple python object (try using __dict__) or use a specialized encoder. – Andreas Klebinger Dec 12 '13 at 10:46
  • what do you mean by simple python object ? – Basj Dec 12 '13 at 10:46
  • Simple python objects are from the top of my head only lists, dictionaries, arrays and strings/numbers. – Andreas Klebinger Dec 12 '13 at 10:47