5

This seems to be a very straightforward problem where I am trying to read a JSON file and modify a few of the fields.

with open("example.json", "r+") as f: data = json.load(f) # perform modifications to data f.truncate(0) json.dump(data, f) 

It worked the first time I manually created a JSON file and stored the correct JSON file, but by the second time I run the same script it gives me this error:

ValueError: No JSON object could be decoded

Why is that? It surprises me that the json module cannot parse the file created by the module itself.

11
  • Could you post the file contents? Commented Jul 18, 2017 at 0:16
  • @Chris The original JSON file I manually made with vim only contains {}. The script did perform the expected modifications and stored the correct JSON string back to the file (without a newline at the end.) Commented Jul 18, 2017 at 0:18
  • 2
    I'm not sure what the rest of the code looks like, but f.truncate clears the file, it does not return your file cursor back to the beginning of the file. If you are looking to bring the cursor back to the beginning of the file you are looking for f.seek(0). Commented Jul 18, 2017 at 0:20
  • So you started with a manually created file, ran your code, then ran it again and the 2nd time you ran it got the error? Commented Jul 18, 2017 at 0:21
  • @Chris That is correct. Commented Jul 18, 2017 at 0:21

2 Answers 2

3

Based on the code you provided, and what you are trying to do (return the file cursor back to the beginning of the file), you are not actually doing that with f.truncate. You are actually truncating your file. i.e. Clearing the file entirely.

Per the help on the truncate method:

truncate(...) truncate([size]) -> None. Truncate the file to at most size bytes. Size defaults to the current file position, as returned by tell(). 

What you are actually looking to do with returning the cursor back to the beginning of the file is using seek.

The help on seek:

seek(...) seek(offset[, whence]) -> None. Move to new file position. 

So, explicitly, to get back to the beginning of the file you want f.seek(0).

For the sake of providing an example of what is happening. Here is what happens with truncate:

File has stuff in it:

>>> with open('v.txt') as f: ... res = f.read() ... >>> print(res) 1 2 3 4 

Call truncate and see that file will now be empty:

>>> with open('v.txt', 'r+') as f: ... f.truncate(0) ... 0 >>> with open('v.txt', 'r') as f: ... res = f.read() ... >>> print(res) >>> 

Using f.seek(0):

>>> with open('v.txt') as f: ... print(f.read()) ... print(f.read()) ... f.seek(0) ... print(f.read()) ... 1 2 3 4 0 1 2 3 4 >>> 

The long gap between the first output shows the cursor at the end of the file. Then we call the f.seek(0) (the 0 output is from the f.seek(0) call) and output our f.read().

Sign up to request clarification or add additional context in comments.

Comments

1

You are missing one line, f.seek(0)

with open("example.json", "r+") as f: data = json.load(f) # perform modifications to data f.seek(0); f.truncate(0) json.dump(data, f) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.