9

My python script generates json file. And I have to support this python file working on windows and linux. The problem is a difference carriage return on windows and linux. When I run this code on windows, it outputs CRLF json. And it outputs LF json when I run this on linux.

So how to explicitly set carriage return when doing json dump in python3.5? I couln

import json
fpath = "hoge.json"
data = {"AGE": 12, "HOGE": [{"GUA": 3}]}
with open(fpath, 'wt', encoding="utf-8") as outfile:
    json.dump(data, outfile, indent=4, sort_keys=True, ensure_ascii=False)

http://docs.python.jp/3/library/json.html

martineau
  • 119,623
  • 25
  • 170
  • 301
jef
  • 3,890
  • 10
  • 42
  • 76
  • It probably makes more sense to convert the line endings separately after creating the file. Or, even better, just use line-ending-aware code to read it on the other end; most software that reads JSON should be able to cope with an unfamiliar line ending in some way or other. – BrenBarn Jan 25 '17 at 03:32
  • In JSON whitespace characters including `\n` and `\r` and ignored outside of tokens and disallowed (except of space) inside of tokens. So using Windows or UNIX linefeeds does not make a difference. – Klaus D. Jan 25 '17 at 05:04

2 Answers2

13

If you insist on consistent CRLF behavior (the JSON spec requires parsers to handle both, but opening it in certain plain text readers like Notepad might be easier with consistent CRLF), the solution is in the open function, not the json module.

Just pass newline='\r\n' to open, and it will translate any \n written by json to \r\n seamlessly on all systems, rather than the default behavior of translating to os.linesep (which is \r\n on Windows and \n on most other OSes):

with open(fpath, 'w', encoding="utf-8", newline='\r\n') as outfile:
    json.dump(data, outfile, indent=4, sort_keys=True, ensure_ascii=False)
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • 1
    Indeed! I want to set LF, so I could realized it with newline='\n\' – jef Jan 25 '17 at 05:41
  • 1
    @jef: Ah, your question made it sound like you _wanted_ the carriage return. Yeah, if you just want the line feed, use `newline=''` or `newline='\n'`, either of which disable line ending translation (the latter explicitly says "translate LF to LF", the former says "don't translate", but those are logically equivalent behaviors). – ShadowRanger Jan 25 '17 at 05:46
  • I did want the CR so thank you for this. Although "the JSON spec requires parsers to handle both" it is often advantageous to have the JSON file human readable and this fixes that for me. Also fixed an problem I was having with 'smart quotes' – dumbledad Aug 06 '18 at 08:10
2

Line endings are white space in the Json spec (https://www.rfc-editor.org/rfc/rfc7159 section 2 at the bottom):

Insignificant whitespace is allowed before or after any of the six structural characters.

  ws = *(
          %x20 /              ; Space
          %x09 /              ; Horizontal tab
          %x0A /              ; Line feed or New line
          %x0D )              ; Carriage return

This means that every reader must handle both CR and LF to be conformant.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
thebjorn
  • 26,297
  • 11
  • 96
  • 138