json-formatieren.de

Ratgeber · JSON 2026

JSON und UTF-8: Encoding-Edge-Cases die Pipelines killen

JSON ist immer UTF-8, ohne BOM. Aber Windows-Tools schreiben gerne BOMs rein, und Python 2 hatte ein eigenes Problem mit Surrogate-Pairs.

Foto von Mateusz Viola

Von Mateusz Viola

Betreiber & redaktionelle Verantwortung json-formatieren.de

JSON ist immer UTF-8

RFC 8259 schreibt es explizit: "JSON text exchanged between systems that are not part of a closed ecosystem MUST be encoded using UTF-8". Andere Encodings (UTF-16, UTF-32) sind formal noch erlaubt, in der Praxis aber nicht relevant. Wer heute JSON schreibt oder parst, geht immer von UTF-8 aus.

BOM ist verboten

Eine UTF-8-BOM (Byte Order Mark) ist die Byte-Folge EF BB BF am Datei-Anfang. RFC 8259 verbietet sie in JSON explizit. Wer trotzdem eine BOM einfügt, bekommt von JSON.parse:

SyntaxError: Unexpected token  in JSON at position 0

Häufige Verursacher:

  • Windows-Notepad bei "Save as UTF-8" (klassisch, alte Versionen)
  • PowerShell mit Out-File -Encoding utf8 (älter als PS 7)
  • Excel beim CSV-zu-JSON-Konvertieren

Lösung: Editor auf "UTF-8 ohne BOM" stellen. In PowerShell 7+: Out-File -Encoding utf8NoBOM. In VS Code: Statusbar rechts unten klickbar.

Surrogate-Pairs für Codepoints > U+FFFF

JSON-Strings sind als Unicode-Codepoint-Sequenz spezifiziert. Codepoints bis U+FFFF (Basic Multilingual Plane) können direkt als \uXXXX-Sequenz escaped werden. Für höhere Codepoints (typisch Emojis) braucht es Surrogate-Pairs:

ZeichenCodepointJSON-Escape
äU+00E4\u00e4
U+20AC\u20ac
😀U+1F600\uD83D\uDE00
𝄞U+1D11E\uD834\uDD1E

Surrogate-Pairs sind ein UTF-16-Konstrukt, das sich in JSON-Escape-Sequenzen niederschlägt. JSON.stringify in V8 nutzt heute lieber direkte UTF-8-Bytes statt Escape-Sequences - kürzer und genauso valide.

Lone Surrogates: der dunkle Edge-Case

JavaScript-Strings sind UTF-16, und es ist technisch möglich, einen "lone surrogate" zu haben - also nur die obere oder untere Hälfte eines Surrogate-Pairs. JSON.stringify in modernen V8-Versionen ersetzt solche Lone Surrogates durch das Replacement-Character U+FFFD (). Ältere Implementierungen geben sie unverändert raus - und der resultierende JSON ist dann nicht valides UTF-8.

Pflicht-Test in API-Pipelines: prüfen ob alle eingehenden Strings valide UTF-8 produzieren würden. Library: well-formed für JS.

Encoding-Pflichten pro Sprache

SpracheDefaultAnmerkung
JavaScriptUTF-8 (kein BOM)JSON.stringify garantiert es
Python 3UTF-8json.dumps(ensure_ascii=False) für lesbare Output
GoUTF-8encoding/json garantiert es
Javaabhängig vom WriterOutputStreamWriter mit "UTF-8" explizit setzen
PowerShell 5UTF-8 mit BOM (!)Out-File -Encoding utf8 schreibt BOM. PS7+: utf8NoBOM nutzen

HTTP-Header und Encoding

Im Content-Type-Header brauchst du kein charset-Suffix:

Content-Type: application/json          // korrekt
Content-Type: application/json; charset=utf-8  // redundant, aber harmlos

RFC 8259 sagt: JSON-Mediatype ist per Definition UTF-8. Der charset-Parameter ist nicht definiert und wird von Parsern ignoriert. Schadet aber auch nicht - viele Frameworks (Spring, Express) setzen ihn aus Habitus.

Praxis-Empfehlung

  1. JSON nie als UTF-16 oder UTF-32 ausgeben - nutze immer UTF-8.
  2. BOM strippen vor Parsing wenn du Dateien aus Windows-Systemen liest.
  3. Bei API-Boundary: incoming Payloads auf valides UTF-8 prüfen, vor Schema-Validation.
  4. JSON.stringify als Default vertrauen - es macht das Richtige seit Jahren.

Mehr zum Thema