← Tous les articles

Caractère mal échappé en JSON : causes, exemples et correctifs

Corrigez les erreurs « bad escaped character in JSON » : échappements \x, chemins Windows, regex, \u mal formés et JSON doublement encodé.

SyntaxError: Bad escaped character in JSON at position N signifie que le parser a trouvé un antislash (\) à l’intérieur d’une chaîne JSON, puis que le caractère suivant n’était pas l’un des caractères d’échappement autorisés par JSON. D’après la section 7 de la RFC 8259, les chaînes JSON peuvent échapper un guillemet double, un antislash, une barre oblique, les échappements de contrôle b, f, n, r, t, ou un échappement Unicode écrit comme u suivi d’exactement quatre chiffres hexadécimaux.

Dans le débogage réel, cette erreur provient généralement d’une seule valeur copiée : un chemin Windows (C:\Users\Ada), un échappement JavaScript ou shell (\x1b), un motif regex (\d+), un échappement Unicode de type Python (\U0001F600), ou une chaîne à moitié déséchappée depuis un log. Le correctif n’est pas « supprimer les antislashs ». Le correctif consiste à décider quelle doit être la valeur finale de la chaîne, puis à écrire le texte JSON qui représente cette valeur.

Ce guide se concentre sur la formulation de JSON.parse() en JavaScript, mais la même règle s’applique à json.loads() en Python, encoding/json en Go, JSON.parse en Ruby, json_decode en PHP, jq, jsonb de Postgres, et à la plupart des parsers JSON stricts.

Quelle erreur de chaîne est-ce que je vois ?

  • Bad escaped character : un \ est suivi de quelque chose que JSON n’autorise pas, par exemple \x, \d, \', ou \Users.
  • Bad control character : une tabulation, un saut de ligne, un octet NUL ou un octet ESC ANSI brut apparaît à l’intérieur d’une chaîne.
  • Unterminated string : une chaîne ouverte avec " mais jamais refermée.

Le correctif en 30 secondes

  1. Rendez-vous à la position, line ou column indiquée.
  2. Regardez le caractère juste avant : cherchez un antislash.
  3. Vérifiez le caractère qui suit l’antislash.
  4. Si l’antislash fait partie des données, écrivez-le \\.
  5. Si l’échappement appartient à un autre langage (\x, \d, \U), traduisez-le en syntaxe JSON.
  6. Si l’antislash a seulement été copié depuis une ligne de log entre guillemets, analysez une couche plutôt que de le supprimer avec une regex.

Exemple :

{"path":"C:\Users\Ada\file.json"}
           ^
           U n'est pas valide après un antislash JSON

Texte JSON correct :

{
  "path": "C:\\Users\\Ada\\file.json"
}

Après l’analyse, la valeur réelle dans l’application reste :

C:\Users\Ada\file.json

Les antislashs doublés n’existent que dans le texte JSON.

À quoi ressemble l’erreur

Les différents moteurs utilisent une formulation légèrement différente :

// V8 : Chrome, Node.js, Edge
SyntaxError: Bad escaped character in JSON at position 12

// Firefox
SyntaxError: JSON.parse: bad escaped character at line 1 column 13 of the JSON data

// Safari
SyntaxError: JSON Parse error: Invalid escape character \x

La position de V8 pointe généralement sur le caractère qui suit l’antislash, pas sur l’antislash lui-même. Dans ce JSON cassé, le caractère signalé est le U de \Users :

{"path":"C:\Users\Ada\file.json"}
           ^^
           \U est le mauvais échappement

Ainsi, quand le message indique position 12, inspectez une petite fenêtre avant et après la position 12. Le caractère fautif est utile, mais c’est l’antislash qui le précède qui explique le bug.

Les seuls échappements que JSON autorise

À l’intérieur d’une chaîne JSON, un antislash ne peut introduire que ces échappements :

Échappement JSON Caractère analysé Notes
\" " Obligatoire pour un guillemet double à l’intérieur d’une chaîne JSON
\\ \ Obligatoire pour un antislash littéral
\/ / Optionnel ; / est aussi valide non échappé
\b Retour arrière U+0008
\f Form feed U+000C ; c’est pourquoi \file est dangereux dans les chemins Windows
\n Saut de ligne U+000A
\r Retour chariot U+000D
\t Tabulation U+0009
\uXXXX Unité de code Unicode Exactement quatre chiffres hex après un u minuscule

Tout le reste est du JSON invalide : \x, \', \d, \s, \w, \0, \v, \e, \U, \u{1F600}, \N{...}, \cA, et les échappements Unicode courts comme \u12.

Tableau des correctifs rapides

Utilisez ce tableau quand vous savez déjà quelle doit être la valeur finale.

Texte JSON cassé Pourquoi ça échoue Texte JSON valide
{ "path": "C:\Users\Ada\file.json" } \U et \A sont invalides ; \f est valide mais devient un form feed, pas un séparateur de chemin. { "path": "C:\\Users\\Ada\\file.json" }
{ "path": "C:/Users/Ada/file.json" } Cela n’échoue pas. Les barres obliques n’ont pas besoin d’être échappées. Conservez-le si le consommateur accepte les barres obliques.
{ "color": "\x1b[32mOK\x1b[0m" } JSON n’a pas d’échappement \xNN. { "color": "\u001b[32mOK\u001b[0m" }
{ "name": "O\'Brien" } Les apostrophes n’ont pas besoin d’être échappées dans les chaînes JSON. { "name": "O'Brien" }
{ "pattern": "^\d{4}-\d{2}-\d{2}$" } \d est un échappement regex, pas un échappement JSON. { "pattern": "^\\d{4}-\\d{2}-\\d{2}$" }
{ "char": "\u12" } \u doit être suivi d’exactement 4 chiffres hex. { "char": "\u0012" }
{ "emoji": "\u{1F600}" } JavaScript le supporte dans les chaînes source ; JSON non. { "emoji": "😀" } ou { "emoji": "\uD83D\uDE00" }

Un détail délicat mérite son propre avertissement : \f est un échappement JSON valide. Si un chemin Windows contient \file, un parser peut le transformer en un caractère form feed suivi de ile. L’analyse peut réussir alors que la valeur du chemin est corrompue. C’est pourquoi « réparer » aveuglément des chaînes de chemin est risqué.

Cause 1 : chemins Windows copiés dans du JSON

Les chemins Windows paraissent inoffensifs parce que les humains lisent l’antislash comme un séparateur de chemin :

{ "downloadDir": "C:\Users\Ada\Downloads" }

JSON lit l’antislash comme le début d’une séquence d’échappement. Il voit \U, puis s’arrête parce que le U majuscule n’est pas un échappement JSON.

Écrivez des antislashs doublés en JSON :

{
  "downloadDir": "C:\\Users\\Ada\\Downloads"
}

Ou utilisez des barres obliques si le programme récepteur les accepte :

{
  "downloadDir": "C:/Users/Ada/Downloads"
}

Pour les fichiers de config, les barres obliques provoquent souvent moins d’erreurs. Pour des valeurs strictement Windows, les antislashs doublés sont la représentation JSON portable.

Cause 2 : mélanger les chaînes source JavaScript avec le texte JSON

C’est là que beaucoup d’exemples sur le web sèment involontairement la confusion. Il y a deux couches :

  • La syntaxe des chaînes source JavaScript
  • La syntaxe du texte JSON à l’intérieur de cette chaîne JavaScript

Ce code source JavaScript est valide :

const raw = '{"path":"C:\\Users\\Ada"}';
JSON.parse(raw);

Mais le texte JSON qui atteint le parser est :

{"path":"C:\\Users\\Ada"}

Si vous voulez tester un échantillon de JSON cassé en JavaScript sans que JavaScript lui-même consomme d’abord les antislashs, utilisez String.raw :

const broken = String.raw`{"path":"C:\Users\Ada"}`;
JSON.parse(broken);

Cela lève Bad escaped character parce que JSON.parse() reçoit le vrai texte JSON cassé.

Utilisez ce modèle mental à la lecture des stack traces : si le JSON vient d’un fichier .json, d’un corps HTTP, d’une valeur localStorage ou d’une chaîne en base de données, corrigez le texte JSON. Si le JSON est à l’intérieur d’une chaîne source JavaScript, vous aurez peut-être besoin d’un niveau d’échappement pour JavaScript et d’un autre pour JSON.

Cause 3 : emprunter des échappements à d’autres langages

JSON accepte \n et \t, mais il n’accepte pas beaucoup d’échappements normaux dans les langages de programmation :

{ "code": "\x1b[0m", "name": "O\'Brien" }

JSON valide :

{
  "code": "\u001b[0m",
  "name": "O'Brien"
}

Faux amis courants :

Échappement Valide en Correctif JSON
\x1b JavaScript, Python, de nombreux shells \u001b
\' Chaînes à guillemets simples JavaScript/Python Utilisez ' sans antislash
\0 Raccourci NUL JavaScript/Python \u0000
\v Tabulation verticale JavaScript \u000b
\U0001F600 Échappement Unicode Python Emoji UTF-8 littéral ou paire de substitution
\u{1F600} Échappement de point de code Unicode JavaScript Emoji UTF-8 littéral ou paire de substitution

Si le producteur est votre code, ne traduisez pas chaque cas à la main. Construisez un objet normal et laissez le sérialiseur JSON du langage écrire un JSON valide.

Cause 4 : motifs regex stockés dans la config JSON

Les regex ont leur propre langage d’échappement. Les chaînes JSON ont un langage d’échappement distinct. L’antislash du regex doit survivre à l’analyse JSON avant de pouvoir atteindre le moteur regex.

Config JSON cassée :

{ "datePattern": "^\d{4}-\d{2}-\d{2}$" }

Config JSON valide :

{
  "datePattern": "^\\d{4}-\\d{2}-\\d{2}$"
}

Après l’analyse JSON, l’application voit cette chaîne :

^\d{4}-\d{2}-\d{2}$

C’est seulement à ce moment qu’elle doit devenir une expression régulière :

const config = JSON.parse('{"datePattern":"^\\\\d{4}-\\\\d{2}-\\\\d{2}$"}');
const re = new RegExp(config.datePattern);

La même règle s’applique à \s, \w, \b, aux groupes nommés, aux exemples de lookbehind et aux chaînes de remplacement. Si l’antislash est destiné à un parser ultérieur, doublez-le dans le JSON.

Cause 5 : échappements Unicode mal formés

L’échappement Unicode de JSON est de largeur fixe :

{ "char": "\u12" }

JSON valide :

{
  "char": "\u0012"
}

Le u doit être en minuscule et suivi d’exactement quatre chiffres hex : 0-9, a-f ou A-F.

Ceux-ci ne sont pas des échappements Unicode JSON :

"\u{2028}"   // style source JavaScript, pas JSON
"\U00002028" // style Python, pas JSON
"\u20G0"     // G n'est pas un chiffre hex

Les caractères en dehors du Plan Multilingue de Base, comme beaucoup d’emojis et certains symboles mathématiques, peuvent être stockés littéralement en JSON UTF-8 :

{
  "emoji": "😀"
}

Sous forme échappée, ils sont représentés par une paire de substitution UTF-16 :

{
  "emoji": "\uD83D\uDE00"
}

Évitez les substituts orphelins tels que \uD83D sans le substitut bas correspondant. Certains parsers les acceptent comme unités de code, mais les systèmes en aval qui exigent un Unicode bien formé peuvent les rejeter.

Cause 6 : chaînes JSON construites à la main

Voici la version en production du bug :

// Non sûr : userInput peut contenir des antislashs, des guillemets ou des sauts de ligne.
const payload = '{"message":"' + userInput + '"}';

Si userInput vaut C:\Users\Ada, le texte émis est du JSON invalide. S’il contient ", le JSON peut se casser d’une autre manière. S’il contient un saut de ligne brut, vous pouvez obtenir un « bad control character » à la place.

Utilisez un sérialiseur :

const payload = JSON.stringify({
  message: userInput,
  path: 'C:\\Users\\Ada\\file.json',
  code: '\x1b[32mOK\x1b[0m',
});

JSON.stringify() gère l’échappement spécifique à JSON. Le résultat est un texte JSON valide :

{
  "message": "...",
  "path": "C:\\Users\\Ada\\file.json",
  "code": "\u001b[32mOK\u001b[0m"
}

Le même principe s’applique dans d’autres langages :

import json

payload = json.dumps({
    "path": r"C:\Users\Ada\file.json",
    "pattern": r"^\d+$",
})
body, err := json.Marshal(map[string]string{
    "path": `C:\Users\Ada\file.json`,
    "pattern": `^\d+$`,
})

Si vous corrigez un producteur, c’est le vrai correctif. Rapiécer du JSON invalide en aval ne fait que masquer l’endroit où le mauvais texte a été créé.

Comment localiser le mauvais échappement

Pour du JSON collé, ce petit utilitaire rend la zone autour de la position de V8 plus facile à voir :

function showJsonParseContext(raw) {
  try {
    JSON.parse(raw);
    console.log('Valid JSON');
  } catch (error) {
    const message = String(error.message);
    const match = message.match(/position (\d+)/);

    if (!match) {
      console.log(message);
      return;
    }

    const pos = Number(match[1]);
    const start = Math.max(0, pos - 24);
    const end = Math.min(raw.length, pos + 24);
    const excerpt = raw.slice(start, end);

    console.log(message);
    console.log(JSON.stringify(excerpt));
    console.log(' '.repeat(pos - start) + '^');
  }
}

const raw = String.raw`{"path":"C:\Users\Ada\file.json"}`;
showJsonParseContext(raw);

JSON.stringify(excerpt) est intentionnel. Il affiche les antislashs et les caractères de contrôle sous forme d’échappements visibles, ce qui est exactement ce qu’il faut quand le bug est un blanc invisible ou un échappement trop zélé.

Pour les erreurs de type Firefox avec line et column, sautez d’abord à cette ligne, puis inspectez le littéral de chaîne sur cette ligne. Si la colonne exacte tombe après un antislash, lisez aussi le caractère précédent.

Outil de réparation ou rejet du payload ?

Utilisez un outil de réparation quand :

  • Vous nettoyez un extrait collé.
  • Vous déboguez une ligne de log.
  • Vous relisez la sortie d’un LLM.
  • Vous pouvez confirmer visuellement la valeur réparée.
  • La valeur ne pilote pas de mouvement d’argent, de permissions, de suppression ou de changement d’état irréversible.

Rejetez le payload et corrigez le producteur quand :

  • Le JSON provient d’un contrat d’API.
  • La valeur affecte la facturation, les permissions, la sécurité ou la suppression de données.
  • Le parser a dû deviner entre plusieurs significations possibles.
  • Un chemin, une regex ou une séquence d’échappement pourrait être valide mais sémantiquement faux.

Par exemple, réparer C:\Users\Ada\file.json n’est pas juste une opération syntaxique. \f dans \file est un échappement valide, donc un outil peut analyser un caractère form feed au lieu de préserver l’antislash. Un humain ou le code producteur doit décider du chemin voulu.

L’outil JSON Fix de ce site s’utilise mieux comme un assistant de débogage local au navigateur : collez le texte, inspectez la sortie, puis validez le JSON réparé. Il ne doit pas être la couche d’ingestion silencieuse de payloads de production mal formés.

Comment déséchapper du JSON en toute sécurité

Parfois les antislashs ne sont pas mauvais ; le JSON est doublement encodé. Vous pouvez voir cela dans les logs :

{\"name\":\"Ada\",\"path\":\"C:\\\\Users\\\\Ada\"}

N’exécutez pas un replace(/\\/g, '') global. Cela détruit les vrais échappements.

Analysez une couche JSON valide à la fois :

// La valeur externe est une chaîne JSON qui contient du texte JSON.
const wrapped = '"{\\"name\\":\\"Ada\\",\\"path\\":\\"C:\\\\\\\\Users\\\\\\\\Ada\\"}"';

const once = JSON.parse(wrapped);
// once vaut : {"name":"Ada","path":"C:\\Users\\Ada"}

const data = JSON.parse(once);
// data vaut : { name: "Ada", path: "C:\\Users\\Ada" }

Si le premier parse échoue avec Bad escaped character, l’entrée n’est pas simplement encodée. C’est du texte JSON invalide qui a besoin d’une réparation ciblée.

Liste de prévention

  • Ne concaténez jamais des chaînes utilisateur dans du JSON.
  • Utilisez JSON.stringify(), json.dumps(), json.Marshal(), ou le sérialiseur JSON de votre plateforme.
  • Stockez les motifs regex en JSON avec des antislashs doublés.
  • Préférez les barres obliques pour les chemins quand le consommateur les accepte.
  • Encadrez et testez les exemples copiés depuis les logs, les shells et la doc.
  • Validez les fichiers .json générés en CI avec un vrai parser.
  • Journalisez un aperçu sûr autour de la position du parser au lieu de logger tout le payload.
  • Traitez la réparation automatique comme un workflow de développeur, pas comme un contrat de production.

Questions fréquentes

Que signifie « Bad escaped character in JSON » ?

Un antislash à l’intérieur d’une chaîne JSON est suivi d’un caractère que JSON n’autorise pas après \. Les échappements valides sont ", \, /, b, f, n, r, t et uXXXX.

Comment corriger un chemin Windows en JSON ?

Écrivez chaque antislash du chemin \\, par exemple C:\\Users\\Ada\\file.json. Si le programme récepteur accepte les barres obliques, C:/Users/Ada/file.json est du JSON valide et plus lisible.

Pourquoi ma regex fonctionne-t-elle en JavaScript mais échoue en JSON ?

Le parser JSON voit la chaîne avant le moteur regex. Un échappement regex comme \d doit être écrit \\d en JSON pour que la chaîne analysée contienne toujours \d.

Est-ce que \x1b est du JSON valide ?

Non. \xNN est courant en JavaScript, Python et dans les exemples shell, mais JSON ne le supporte pas. Utilisez \u001b pour le caractère ANSI ESC, ou retirez les codes de couleur ANSI avant de sérialiser les logs.

Est-ce la même chose que « Bad control character » ?

Non. « Bad escaped character » signifie que le caractère qui suit un antislash est invalide. « Bad control character » signifie qu’un octet de contrôle brut, comme un saut de ligne, une tabulation, un NUL ou un ESC littéral, apparaît à l’intérieur d’une chaîne JSON.

Les outils de réparation JSON peuvent-ils corriger automatiquement les mauvais échappements ?

Parfois, pour des extraits collés où la valeur voulue est évidente. N’auto-réparez pas silencieusement les payloads d’API, les données sensibles à la sécurité, les paiements, les permissions, les suppressions, ou les valeurs où \f, \n ou \t pourraient être valides mais non voulus.

Comment déséchapper du JSON ?

Analysez une couche à la fois avec JSON.parse(). Une valeur doublement encodée devient une chaîne JSON normale après le premier parse et un vrai objet ou tableau après le second. Évitez le retrait d’antislash par regex car cela corrompt les échappements valides.

Comment prévenir cette erreur dans le code source ?

Construisez des valeurs natives et sérialisez-les avec JSON.stringify() ou le sérialiseur équivalent dans votre langage. N’assemblez pas du JSON par concaténation de chaînes.

Corriger maintenant

Sources

Dernière révision : juillet 2026.