# U+00A0, ce caractère invisible qui fait planter un analyseur JSON headless

> Une erreur de parsing JSON qui n'apparaît qu'une fois sur mille : l'espace insécable copiée depuis un traitement de texte, invisible à l'œil, fatale à un analyseur strict.

- Auteur : WordPress Développement
- Publié le : 2022-11-29
- Mis à jour le : 2022-11-29
- Catégorie : Headless &amp; API
- URL : https://www.wpmoderne.fr/headless/espace-insecable-json-analyseur-headless/

## L’essentiel

- Un caractère U+00A0 invisible casse un parseur JSON strict
- La copie depuis un traitement de texte en est souvent la source
- Un assainissement avant sérialisation règle le problème durablement

`SyntaxError: Unexpected token in JSON at position 214`. Ce message, un développeur qui exploite une API headless finit toujours par le croiser un jour, et le plus souvent au pire moment : en production, sur un contenu qui semblait parfaitement anodin. Le champ fautif est un simple paragraphe de description produit, recopié depuis un document Word par une personne du service marketing. Rien à l'œil nu ne distingue l'espace qui sépare deux mots de celui qui a cassé l'analyseur.

Le coupable porte un nom précis : `U+00A0`, l'espace insécable Unicode. Visuellement identique à une espace ordinaire, il ne l'est pas du tout pour un moteur de sérialisation JSON strict, et surtout pas pour certains analyseurs côté front qui appliquent des règles de validation supplémentaires sur les chaînes reçues. Ce billet détaille comment repérer ce genre d'incident, comment le diagnostiquer sans y passer une journée, et comment l'empêcher de revenir.

## Le symptôme : un échec rare et capricieux

Le signalement typique ressemble à ceci : « la page produit numéro 4 128 affiche une erreur, mais la 4 127 fonctionne très bien ». Le contenu, dans l'éditeur WordPress, est strictement identique visuellement. La réponse de la route REST, elle, contient un octet différent. C'est ce qui rend ce genre de bogue si difficile à reproduire à la demande : il ne dépend d'aucune condition logique, seulement de la provenance du texte collé dans l'éditeur.

Sur un projet headless qui agrège plusieurs centaines de fiches, ce type d'incident touche rarement plus d'une poignée de contenus, ce qui le rend d'autant plus insidieux : les tests manuels passent, l'intégration continue passe, et seul un utilisateur réel finit par tomber dessus.

## Le diagnostic : retrouver l'octet fautif

La première étape consiste à isoler la réponse JSON brute plutôt que son rendu dans le navigateur, qui masque la plupart des caractères invisibles. Une commande simple suffit à révéler la présence d'un octet suspect :

```
curl -s https://exemple.test/wp-json/wp/v2/produit/4128 \
  | php -r "echo bin2hex(file_get_contents('php://stdin'));" \
  | grep -o 'c2a0'
```

> L'essentiel à retenir : Un caractère U+00A0 invisible casse un parseur JSON strict ; La copie depuis un traitement de texte en est souvent la source ; Un assainissement avant sérialisation règle le problème durablement

La séquence `c2` `a0` correspond à l'encodage UTF-8 de `U+00A0`. Sa présence dans un champ texte confirme le diagnostic sans ambiguïté. Il est également possible de le repérer directement en base de données, dans la table `wp_postmeta` ou `wp_posts` selon l'emplacement du champ concerné, avec une requête ciblée sur l'octet en question.

### Pourquoi certains analyseurs tolèrent le caractère et d'autres non

Le format JSON, au sens strict de la RFC, autorise parfaitement `U+00A0` à l'intérieur d'une chaîne de caractères : ce n'est pas un caractère de contrôle interdit. Le problème vient généralement d'une étape intermédiaire : un middleware de validation côté front qui applique une expression régulière trop stricte sur les espaces, ou un composant de recherche qui indexe le texte en le comparant caractère par caractère à une saisie clavier classique. La faute n'est donc pas dans le JSON lui-même, mais dans ce qui le consomme ensuite.

## Le correctif : assainir avant de sérialiser

La solution la plus robuste ne consiste pas à corriger chaque contenu un par un, mais à normaliser systématiquement les chaînes avant qu'elles n'atteignent la réponse de l'API. La fonction `register_rest_field()` permet d'appliquer un filtre de nettoyage au moment de la construction de la réponse :

```
add_filter( 'rest_prepare_produit', function ( $response, $post, $request ) {
    $data = $response->get_data();
    if ( isset( $data['excerpt']['rendered'] ) ) {
        $data['excerpt']['rendered'] = str_replace(
            "\xC2\xA0",
            ' ',
            $data['excerpt']['rendered']
        );
    }
    $response->set_data( $data );
    return $response;
}, 10, 3 );
```

Cette approche traite le symptôme à la source de la diffusion, sans toucher au contenu original stocké en base, ce qui évite d'altérer la mise en forme voulue par l'auteur dans l'éditeur.

## La prévention : détecter avant la publication

Un correctif ponctuel ne suffit pas si la source du problème persiste : les personnes qui rédigent du contenu continueront de copier des paragraphes depuis des traitements de texte. Plusieurs pistes complémentaires réduisent la récurrence :

- Ajouter une vérification automatisée dans le processus de publication qui détecte la présence de `U+00A0` et alerte l'auteur avant l'enregistrement.
- Documenter la pratique de collage en texte brut (`Ctrl+Maj+V`) dans les consignes de rédaction internes.
- Ajouter un test automatisé dans la suite d'intégration continue qui interroge un échantillon de routes REST et signale tout octet `c2 a0` non attendu.

> Un assainissement systématique en sortie d'API coûte quelques lignes de code ; traquer un incident après coup sur un contenu parmi des milliers en coûte une demi-journée. Le calcul est vite fait.

## En résumé

Ce type d'incident illustre une réalité fréquente du développement headless : la frontière entre WordPress et le front n'élimine pas les problèmes d'encodage, elle les déplace simplement plus loin dans la chaîne, là où ils deviennent plus coûteux à diagnostiquer. Un filtre de normalisation appliqué systématiquement au niveau de la réponse REST protège durablement contre ce genre de surprise, sans dépendre de la vigilance de chaque rédacteur.
