Aller au contenu
jsonbeautifiers
Français

JSON en CSV

Objets et tableaux imbriqués traités explicitement, sans limite de taille et sans envoi.

JSON
CSV

Rien de ce que vous collez ne quitte votre navigateur. La liste d’autorisation connect-src en fait une garantie du navigateur plutôt qu’une promesse. Vérifiez-le vous-même

Le CSV est rectangulaire et le JSON est un arbre : tout convertisseur doit donc trancher une série de cas ambigus. La plupart le font en silence. Cette page les tranche, les annonce, et vous laisse les changer.

Il n’y a ni limite de taille de fichier ni quota quotidien, parce qu’il n’y a aucun serveur pour en imposer un.

Les colonnes sont l’union, pas le premier objet

La décision la plus lourde de conséquences. Un convertisseur qui lit les clés de l’élément zéro supprime en silence tous les champs qui n’apparaissent que dans des enregistrements ultérieurs, et vous le découvrez en aval, quand une colonne manque dans un rapport.

Celui-ci collecte tous les chemins sur toutes les lignes, dans l’ordre où chacun est apparu. C’est plus lent et c’est correct. Papa Parse, la bibliothèque CSV JavaScript la plus répandue, prend le premier objet par défaut et exige une option columns explicite pour faire autrement : bon à savoir si vous construisez cela vous-même.

Tableaux dans une ligne : quatre politiques, une valeur par défaut

C’est le cas véritablement ambigu, et il n’y a pas de bonne réponse, seulement un bon défaut.

Colonnes indexées, le défaut
tags.0, tags.1 et ainsi de suite. Sans perte et réversible. Un seul long tableau fait exploser le nombre de colonnes, et c’est le prix à payer.
Fusionner dans une cellule
Valeurs jointes par un point-virgule. Lisible, avec perte, et risqué si une valeur contient le séparateur.
JSON dans une cellule
Le tableau sérialisé en texte JSON. Sans perte et compact, mais à ré-analyser en aval.
Éclater en lignes
Une ligne de sortie par élément du tableau, en répétant les colonnes scalaires. C’est le record_path de json_normalize de pandas. Correct pour une relation un-à-plusieurs et faux pour tout le reste : c’est donc à activer, et cela s’applique à un chemin nommé.

Deux choses au sujet d’Excel qui ne sont pas optionnelles

La marque d’ordre des octets UTF-8
Excel ne détecte pas l’UTF-8 dans un CSV. Sans BOM en tête de fichier, il lit les octets dans la page de codes système et tous les caractères accentués et les émojis arrivent corrompus. Le BOM est activé par défaut ici pour exactement cette raison, et le désactiver est à un clic pour les chaînes de traitement qui s’y étranglent.
Injection de formules
Une cellule commençant par =, +, - ou @ est exécutée comme une formule par Excel, Google Sheets et LibreOffice. Une valeur =HYPERLINK("http://evil","cliquez") dans un CSV que vous avez généré devient un lien actif dans le tableur de quelqu’un d’autre. L’OWASP appelle cela l’injection CSV. Ces cellules reçoivent par défaut une apostrophe en préfixe, et l’outil vous dit quand il l’a fait.

null face à la chaîne vide

Ce sont des valeurs différentes en JSON et Excel affiche les deux comme vides : la plupart des convertisseurs les confondent et la distinction est perdue. Ici null devient une cellule vide sans guillemets et la chaîne vide une cellule vide entre guillemets, ce qui fait survivre l’aller-retour. Cela coûte deux caractères par chaîne vide et cela en vaut la peine.

How to do this in code

Convertir en code, avec les arguments qui décident si c’est correct.

py Python, pandas

encoding="utf-8-sig" est la façon pandas d’écrire le BOM dont Excel a besoin. Un utf-8 simple produit un fichier qu’Excel lit de travers.

import pandas as pd

# Flatten nested objects to dotted columns
df = pd.json_normalize(records)
df.to_csv('out.csv', index=False, encoding='utf-8-sig')

# One row per element of a nested array
df = pd.json_normalize(records, record_path='items', meta=['id'])
sh jq

Utilisez @csv plutôt que de l’interpolation de chaînes. Il applique les règles de guillemets à votre place.

# Union of keys as the header, then the rows
jq -r '(map(keys) | add | unique) as $c
       | $c, (.[] | [.[$c[]]])
       | @csv' records.json > out.csv

# @csv quotes and escapes correctly; @text does not
js JavaScript
import Papa from 'papaparse';

// Pass the union explicitly. Without it, Papa takes the keys of
// the first object and silently drops the rest.
const columns = [...new Set(records.flatMap(Object.keys))];
const csv = Papa.unparse(records, { columns });
go Go
w := csv.NewWriter(f)
w.Write(columns)
for _, rec := range records {
    row := make([]string, len(columns))
    for i, c := range columns {
        row[i] = fmt.Sprint(rec[c])
    }
    w.Write(row)
}
w.Flush()

Questions fréquentes

Pourquoi mon CSV affiche-t-il des caractères bizarres dans Excel ?
Le fichier est en UTF-8 et Excel l’a lu dans la page de codes système. Laissez l’option de marque d’ordre des octets activée. Si le fichier part ailleurs que vers un tableur, désactivez-la, car certains analyseurs traitent le BOM comme faisant partie du nom de la première colonne.
Pourquoi certaines cellules commencent-elles par une apostrophe ?
Parce qu’elles commençaient par =, +, - ou @, que les tableurs exécutent comme des formules. L’apostrophe neutralise cela. Désactivez l’option s’il vous faut la valeur brute et que vous avez confiance dans la destination du fichier.
Et si mes données ne sont pas un tableau d’objets ?
Un objet seul devient une ligne. Un tableau de scalaires devient une colonne. Une enveloppe du type {"data": [...]} utilise le tableau intérieur et vous dit qu’elle a fait ce choix, parce que c’est une supposition et non une règle.
Quel séparateur pour un Excel européen ?
Le point-virgule. Excel choisit son séparateur d’après le séparateur de listes du système, qui est un point-virgule dans les locales où la virgule est le séparateur décimal. C’est pourquoi un fichier séparé par des virgules s’ouvre sur une seule colonne sur une machine allemande ou française.