Programiści

Jak przekonwertować JSON na CSV (bez utraty danych)

7 min czytania

Konwersja JSON na CSV zamienia tablicę obiektów na tabelę: każdy klucz staje się kolumną, każdy obiekt wierszem. Brzmi trywialnie, dopóki wartość nie zawiera przecinka, cudzysłowu albo zagnieżdżonego obiektu. To właśnie zasady escapingu, a nie sama zamiana formatu, sprawiają najwięcej kłopotu i są głównym tematem tego artykułu.

Dlaczego CSV wciąż ma znaczenie

JSON jest naturalnym formatem wymiany danych między API i aplikacjami, ale ludzie wciąż pracują w arkuszach kalkulacyjnych. Excel, Arkusze Google, narzędzia BI i większość potoków importu danych w księgowości czy sprzedaży oczekują płaskiej tabeli, nie zagnieżdżonej struktury drzewiastej. Kiedy trzeba przekazać wynik zapytania API, eksport z bazy danych albo log zdarzeń komuś, kto otworzy plik w arkuszu, CSV pozostaje wspólnym mianownikiem, mimo że istnieje od dekad i nie ma oficjalnego wsparcia dla typów danych czy zagnieżdżenia.

Zweryfikowany przykład: dane, escaping, wynik

Weźmy trzy rekordy produktów z przemyślanie dobranymi wartościami, tak żeby każdy wiersz pokazywał inną regułę escapingu.

[
  { "sku": "A100", "product": "Wireless Mouse, Black", "price": 19.99, "in_stock": true },
  { "sku": "A101", "product": "17\" Laptop Stand", "price": 42.5, "in_stock": false },
  { "sku": "A102", "product": "USB-C Cable", "price": 8.99, "in_stock": true }
]

Nagłówki kolumn to suma kluczy widocznych we wszystkich obiektach tablicy, w kolejności pierwszego wystąpienia: sku, product, price, in_stock. Wynik konwersji wygląda tak:

sku,product,price,in_stock
A100,"Wireless Mouse, Black",19.99,true
A101,"17"" Laptop Stand",42.5,false
A102,USB-C Cable,8.99,true

Warto przejść przez każdy wiersz osobno, bo każdy demonstruje inną sytuację z reguł RFC 4180 (standardu, który definiuje formatowanie plików CSV).

Wiersz 1. Wartość Wireless Mouse, Black zawiera przecinek. Skoro przecinek jest jednocześnie separatorem kolumn, cała wartość zostaje opakowana w cudzysłów: "Wireless Mouse, Black". Bez tego parser CSV odczytałby dwie osobne kolumny zamiast jednej nazwy produktu.

Wiersz 2. Wartość 17" Laptop Stand zawiera pojedynczy znak cudzysłowu (oznaczający cale, siedemnaście cali). Reguła RFC 4180 mówi tu o dwóch krokach naraz: każdy cudzysłów wewnątrz wartości zostaje podwojony (" zamienia się w ""), a cała wartość dodatkowo dostaje zewnętrzną parę cudzysłowów, bo teraz zawiera znak cudzysłowu. Rezultat to "17"" Laptop Stand". To jest dokładnie ten szczegół, który psuje ręcznie pisane konwertery: sam podwojenie cudzysłowu bez zewnętrznego opakowania dałoby nieparsowalny plik.

Wiersz 3. Wartość USB-C Cable nie zawiera przecinka, cudzysłowu ani znaku nowej linii, więc przechodzi bez żadnych zmian, bez cudzysłowów.

Ta sama zasada obejmuje znak nowej linii wewnątrz wartości, na przykład wieloliniowy opis albo notatkę: jeśli komórka zawiera \n, cały fragment też trafia w cudzysłów, żeby parser CSV nie potraktował go jako początku nowego wiersza.

Suma kluczy, nie tylko klucze pierwszego obiektu

Część naiwnych konwerterów patrzy wyłącznie na klucze pierwszego obiektu w tablicy i po cichu gubi kolumny, które pojawiają się dopiero w kolejnych rekordach. Ten konwerter buduje nagłówki jako sumę wszystkich kluczy widzianych w całej tablicy, w kolejności pierwszego wystąpienia, więc żadna kolumna nie znika.

Przykład z brakującym polem:

[
  { "id": 1, "name": "Ala" },
  { "id": 2, "name": "Bartek", "note": "VIP" }
]

Drugi obiekt wprowadza klucz note, którego nie ma w pierwszym. Wynikowe nagłówki to id,name,note, a pierwszy wiersz dostaje pustą komórkę tam, gdzie klucz note nie istniał w oryginalnym obiekcie:

id,name,note
1,Ala,
2,Bartek,VIP

Brakujący klucz nie powoduje błędu, po prostu zostawia puste pole w danym wierszu.

CSV nie zna typów danych

Warto pamiętać o jeszcze jednej różnicy między JSON a CSV, niezwiązanej bezpośrednio z escapingiem, ale równie istotnej przy dalszym przetwarzaniu pliku. W JSON liczba 19.99 i wartość logiczna true mają swój własny typ, parser wie od razu, że to nie jest tekst. W CSV nie ma żadnej informacji o typie, każda komórka to po prostu ciąg znaków. Wartość logiczna true z przykładu wyżej trafia do pliku CSV jako litery t, r, u, e, nieodróżnialne na pierwszy rzut oka od zwykłego tekstu. Konsekwencja jest praktyczna: gdy później wczytujesz ten sam plik z powrotem do programu (na przykład narzędziem odwrotnym, CSV na JSON), musisz sam zdecydować, czy komórka true ma zostać wartością logiczną, czy zostać stringiem, bo sam plik CSV tej decyzji za ciebie nie podejmie. To samo dotyczy liczb: 19.99 w pliku CSV jest tekstem, dopóki coś po drugiej stronie nie zinterpretuje go jako liczbę zmiennoprzecinkową.

Osadzony widżet

Wklej własną tablicę JSON poniżej i sprawdź wynik od razu, bez instalowania niczego.

CSV → JSON JSON → CSV
Konwerter JSON na CSV
Za darmo, bez rejestracji, na każdym urządzeniu.
Otwórz pełne narzędzie

Częste błędy

Obiekty zagnieżdżone zamieniają się w [object Object]. Jeśli wartość klucza jest sama obiektem, na przykład "address": { "city": "Warszawa", "zip": "00-001" }, konwersja do tekstu nie rozpakowuje pól wewnętrznych, tylko zapisuje dosłowny napis [object Object]. To realna pułapka utraty danych: plik CSV wygląda na poprawny, ale kolumna address jest bezużyteczna. Rozwiązanie to spłaszczenie struktury przed konwersją, czyli zamiana jednego zagnieżdżonego klucza address na dwa klucze najwyższego poziomu, na przykład address_city i address_zip, tak żeby każda wartość była tekstem lub liczbą, nigdy obiektem.

Tablice zamieniają się w jeden ciąg oddzielony przecinkami, nie w osobne kolumny. Wartość "tags": ["red", "blue"] nie zostaje rozbita na kilka kolumn. Zostaje zamieniona na pojedynczy ciąg red,blue, czyli elementy tablicy połączone przecinkiem bez żadnych nawiasów kwadratowych. Ponieważ ten ciąg zawiera przecinek, reguła escapingu z poprzedniej sekcji automatycznie opakowuje go w cudzysłów, dając komórkę "red,blue". To zachowanie jest poprawne z punktu widzenia formatu CSV, ale często nie jest tym, czego oczekuje osoba planująca osobną kolumnę na każdy tag. Jeśli potrzebujesz osobnych kolumn, rozbij tablicę na kilka pól przed konwersją, na przykład tag_1, tag_2.

Excel w polskiej wersji językowej oczekuje średnika, nie przecinka. Ten konwerter generuje plik z przecinkiem jako separatorem kolumn, zgodnie z domyślnym CSV. Problem w tym, że w polskich ustawieniach regionalnych przecinek jest separatorem dziesiętnym (piszemy 19,99, nie 19.99), więc Excel w polskiej wersji domyślnie oczekuje średnika jako separatora listy przy otwieraniu pliku CSV. Otwarcie pliku z przecinkami przez podwójne kliknięcie w takim Excelu potrafi wrzucić całą zawartość wiersza do jednej komórki w kolumnie A. Naprawa: w Excelu użyj Dane > Tekst jako kolumny i wybierz ręcznie przecinek jako separator, albo zmień separator listy w ustawieniach regionalnych systemu Windows z powrotem na przecinek, jeśli wolisz, żeby Excel importował plik bezpośrednio.

Pojedynczy obiekt trzeba opakować w nawiasy kwadratowe. Narzędzie oczekuje tablicy obiektów, czyli danych zaczynających się od [ i kończących na ]. Wklejenie samego obiektu, na przykład { "id": 1, "name": "Ala" } bez otaczających nawiasów kwadratowych, nie jest poprawną tablicą JSON i zostanie odrzucone z komunikatem błędu zamiast zawieszenia się aplikacji. Rozwiązanie jest proste: opakuj pojedynczy obiekt w [ i ], nawet jeśli to tylko jeden rekord, [{ "id": 1, "name": "Ala" }].

Najczęściej zadawane pytania

Jakie dane wejściowe akceptuje ten konwerter? Tablicę JSON zawierającą płaskie obiekty, czyli coś w formie [{...}, {...}]. Nieprawidłowy JSON albo dane, które nie są tablicą (na przykład pojedynczy obiekt bez otaczających [ ]), pokazują czytelny komunikat błędu zamiast zawieszać aplikację.

Co się dzieje, gdy jeden obiekt ma inne klucze niż pozostałe? Nagłówki kolumn są sumą wszystkich kluczy widzianych w całej tablicy, w kolejności pierwszego wystąpienia, nie tylko kluczy pierwszego obiektu. Jeśli dany obiekt nie ma jakiegoś klucza, odpowiadająca mu komórka w wierszu zostaje po prostu pusta, bez błędu.

Dlaczego moja kolumna z obiektem zagnieżdżonym pokazuje “[object Object]”? Bo konwersja zamienia wartość na tekst bezpośrednio, a domyślna reprezentacja tekstowa obiektu w JavaScripcie to właśnie literalny napis [object Object], nie rozwinięcie jego pól. Rozwiązanie to spłaszczenie zagnieżdżonej struktury przed konwersją, czyli zamiana na przykład address: { city, zip } na dwa osobne klucze najwyższego poziomu, address_city i address_zip.

Dlaczego Excel psuje mi kolumny po otwarciu wyeksportowanego pliku CSV? Bo plik używa przecinka jako separatora kolumn, a polska wersja Excela domyślnie oczekuje średnika, ponieważ przecinek jest u nas separatorem dziesiętnym. Użyj Dane > Tekst jako kolumny w Excelu i ręcznie wskaż przecinek jako separator, żeby poprawnie rozdzielić kolumny po imporcie.

Czy moje dane są wysyłane na serwer podczas konwersji? Nie. Cała konwersja z JSON na CSV odbywa się lokalnie w przeglądarce, bez wysyłania danych na żaden serwer, więc narzędzie nadaje się też do pracy z danymi wrażliwymi.

Konwerter JSON na CSV
Teraz wypróbuj samodzielnie w pełnym narzędziu.
Wypróbuj teraz
Powiązane narzędzia