Reputation: 69
I'm trying to make a phone book in python and I want to save all contacts in a file, encoded as JSON, but when I try to read the exported JSON data from the file, I get an error:
Extra data: line 1 column 103 - line 1 column 210 (char 102 - 209)
(It works fine when I have only one object in "list.txt")
This is my code:
class contacts:
def __init__(self, name="-", phonenumber="-", address="-"):
self.name= name
self.phonenumber= phonenumber
self.address= address
self.jsonData=json.dumps(vars(self),sort_keys=False, indent=4)
self.writeJSON(self.jsonData)
def writeJSON(self, jsonData):
with open("list.txt", 'a') as f:
json.dump(jsonData, f)
ted=contacts("Ted","+000000000","Somewhere")
with open('list.txt') as p:
p = json.load(p)
print p
The output in list.txt:
"{\n \"phonenumber\": \"+000000000\", \n \"name\": \"Ted\", \n \"address\": \"Somewhere\"\n}"
Now, if I add another object, it can't read the JSON data anymore. If my way of doing it is wrong, how else should I export the JSON code of every object in a class, so it can be read back when I need to?
Upvotes: 2
Views: 3039
Reputation: 1199
The reason this isn't working is that this code path gives you an invalid JSON structure. With one contact you get this:
{"name":"", "number":""}
While with 2 contacts you would end up with this:
{"name":"", "number":""}{"name":"", "number":""}
The second one is invalid json because 2 objects should be encoded in an array, like this:
[{"name":"", "number":""},{"name":"", "number":""}]
The problem with your code design is that you're writing to the file every time you create a contact. A better idea is to create all contacts and then write them all to the file at once. This is cleaner, and will run more quickly since file I/O is one of the slowest things a computer can do.
My suggestion is to create a new class called Contact_Controller and handle your file IO there. Something like this:
import json
class Contact_Controller:
def __init__(self):
self.contacts = []
def __repr__(self):
return json.dumps(self)
def add_contact(self, name="-", phonenumber="-", address="-"):
new_contact = Contact(name,phonenumber,address)
self.contacts.append(new_contact)
return new_contact
def save_to_file(self):
with open("list.txt", 'w') as f:
f.write(str(self.contacts))
class Contact:
def __init__(self, name="-", phonenumber="-", address="-"):
self.name= name
self.phonenumber= phonenumber
self.address= address
def __repr__(self):
return json.dumps({"name": self.name, "phonenumber": self.phonenumber, "address": self.address})
contact_controller = Contact_Controller()
ted = contact_controller.add_contact("Ted","+000000000","Somewhere")
joe = contact_controller.add_contact("Joe","+555555555","Somewhere Else")
contact_controller.save_to_file()
with open('list.txt') as p:
p = json.load(p)
print(p)
I've also changed it to use the built in __repr__()
class method. Python will call that method whenever it needs a string representation of the object.
Upvotes: 3
Reputation: 40763
in writeJSON
, you opened the file for append (mode='a'
), which works fine the first time, but not the subsequent calls. To fix this problem, open the file with overwrite mode ('w'
):
with open("list.txt", 'w') as f:
Upvotes: 0