Saving json file by dumping dictionary in a for loop, leading to malformed json
JSON may only have one root element. This root element can be []
, {}
or most other datatypes.
In your file, however, you get multiple root elements:
{...}{...}
This isn't valid JSON, and the error Extra data
refers to the second {}
, where valid JSON would end instead.
You can write multiple dicts to a JSON string, but you need to wrap them in an array:
[{...},{...}]
But now off to how I would fix your code. First, I rewrote what you posted, because your code was rather pseudo-code and didn't run directly.
import json
inputs = [(["scientific name", "common names", "colors"],
["somename1", ["name11", "name12"], ["color11", "color12"]]),
(["scientific name", "common names", "colors"],
["somename2", ["name21", "name22"], ["color21", "color22"]])]
for keys, values in inputs:
d = dict(zip(keys, values))
with open("file.json", 'a') as j:
json.dump(d, j)
with open("file.json", 'r') as j:
print(json.load(j))
As you correctly realized, this code failes with
json.decoder.JSONDecodeError: Extra data: line 1 column 105 (char 104)
The way I would write it, is:
import json
inputs = [(["scientific name", "common names", "colors"],
["somename1", ["name11", "name12"], ["color11", "color12"]]),
(["scientific name", "common names", "colors"],
["somename2", ["name21", "name22"], ["color21", "color22"]])]
jsonData = list()
for keys, values in inputs:
d = dict(zip(keys, values))
jsonData.append(d)
with open("file.json", 'w') as j:
json.dump(jsonData, j)
with open("file.json", 'r') as j:
print(json.load(j))
Also, for python's json
library, it is important that you write the entire json file in one go, meaning with 'w'
instead of 'a'
.
Dump dictionary to json file as UTF-8
You need to open the file specifying the file encoding.
with open('Data{0}.json'.format(1), 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False)
This way I have dumped your example data sucessfully.
How to write a new dictionary to a json file
There are a few issues here:
file = open('somefile.json', 'a',encoding="utf-8")
You're implicitly assuming that the file will be closed here. That is true on CPython, but not on all Python implementations. A better approach would be:
with open('somefile.json', 'a',encoding="utf-8") as file:
file.write(json_obj)
Because that uses a context manager to explicitly close the file.
Second, you can avoid creating an extra string by writing directly to the file:
with open('somefile.json', 'a',encoding="utf-8") as file:
json.dump(someDict, file)
Third, having multiple JSON objects in a file is not valid JSON. There are a few approaches you could take here. One is to wrap the JSON objects in a list:
[
{
"a": 1,
"b":2,
"c": 3
},
{
"a1": 1,
"b1":2,
"c1": 3
}
]
So, start the file with an open bracket, and write a comma after every JSON object, except the last one, then end the file with a close bracket.
Second approach would be to newline-separate your JSON objects, like this:
{"a": 1,"b":2,"c": 3}
{"a1": 1, "b1":2,"c1": 3}
Each line is a JSON object. You'd read this like so:
with open("filename", "rt") as file:
for line in file:
obj = json.loads(line)
# do something with obj
# ...
The advantage of this approach would be that you can now load each individual JSON object in memory, without having to load the entire file in at once. The disadvantage is that you're no longer writing valid JSON, so you can't use tools like jq
on the output. (If you want the best of both worlds, you can use a package like ijson, but that's more complex.)
Correct way to json.dump() nested dictionary AND read back into python w/ json.load()?
Rather than trying to write yourself a valid json
just let the json.dump
do the heavy-lifting for you. With a main_dict
variable to collect the subdicts, you can just dump it to your file:
import json
main_dict = {}
for number in range(1, 6):
letter_dict = {}
letter = input(f'what letter is in position {number}? ')
if letter:
code = input('what code?:')
else:
print('no additional inputs')
break
letter_dict['letter'] = letter
letter_dict['code'] = code
letter_dict['position'] = number
main_dict[f'dict{number}'] = letter_dict
with open('letters.json', 'w') as file:
json.dump(main_dict, file)
Note that I don't open the file letters.txt
in append mode because a second run of your program would append another dictionary after the first one, thereby making the json
invalid. If you want to append, load the json
file in main_dict
, add a key-value pair to main_dict
and dump again.
How to add a new dictionary into a JSON file?
You need to create a new dictionary containing the information that was entered, and then write the data
dictionary back to the file.
data[productname] = {
"id": id,
"price": price,
"quantity": quantity
}
with open("productos.json", "w") as f:
json.dump(data, f)
Related Topics
How to Use Groupby to Concatenate Strings in Python Pandas
How to Load Existing Db File to Memory in Python SQLite3
How to Convert a Numpy Array to Pil Image Applying Matplotlib Colormap
Retrieving a Foreign Key Value with Django-Rest-Framework Serializers
How to Convert an Array of Strings to an Array of Floats in Numpy
How to Get the Largest Integer One Can Use in Python
Typeerror: Str Does Not Support Buffer Interface
How to Prevent Iterator Getting Exhausted
Creating Over 20 Unique Legend Colors Using Matplotlib
Inheritance of Private and Protected Methods in Python
How Does a Python for Loop with Iterable Work
In-Memory Size of a Python Structure
How to Plot Nan Values as a Special Color with Imshow in Matplotlib
How to Check Blas/Lapack Linkage in Numpy and Scipy