Znění hlášky v jednotlivých prostředích
Hláška PHP mluví o kódování, ale chyba JSON_ERROR_CTRL_CHAR znamená řídicí znak
v řetězci. S kódováním souvisí jen tehdy, když se text přečetl ve špatném kódování a bajt se
omylem stal řídicím znakem.
Příčiny a opravy
Konec řádku přímo v řetězci
{"text":"první\nřádek"}
Víceřádkový text (popis, adresa, poznámka z formuláře) vložený do JSON spojováním řetězců
nese skutečný konec řádku. JSON ho musí mít jako dvojici znaků \n. Mezi
položkami a kolem závorek konce řádků vadit nemusí, jde jen o obsah řetězce.
Tabulátor v řetězci
{"a":"x\ty"} Tabulátor nepoznáš okem: v editoru vypadá jako mezery. Stává se to u textu zkopírovaného z tabulky nebo z výstupu, který odděloval sloupce tabulátorem.
Spolehlivou opravou je vytvářet JSON serializátorem. Ten řídicí znaky escapuje sám:
JSON.stringify({ text: 'první\nřádek\tx' })
// {"text":"první\nřádek\tx"}
json.dumps({'text': 'první\nřádek\tx'}, ensure_ascii=False)
# {"text": "první\nřádek\tx"} Když JSON přichází od někoho jiného
Text s řídicími znaky není platný JSON a oprava patří ke zdroji. Python má pro přechodné
období strict=False, které řídicí znaky v řetězcích přijme. Jiné parsery, třeba
JSON.parse, takovou volbu nemají.
import json
# Jen pro data, která nejdou opravit u zdroje: přijme řídicí znaky v řetězcích.
json.loads('{"text":"první\nřádek"}', strict=False) Nahrazovat konce řádků v celém textu nejde: smazal bys i odsazení mezi položkami, které je v pořádku, a změnil obsah. Pravidla zápisu znaků v řetězcích popisuje kapitola Řetězce v JSON.