Skip to content
Powrót do bloga
Poradniki

Konwersja CSV na JSON: metody, pułapki i przykłady kodu

Konwertuj CSV na JSON (i odwrotnie) w Pythonie, JavaScripcie i narzędziach CLI. Kodowanie, koercja typów oraz strumieniowanie dużych plików.

12 min czytania

Konwersja CSV na JSON: metody, pułapki i najlepsze praktyki

Zespół operacyjny przysyła eksport CSV. Aplikacja oczekuje JSON. Otwierasz plik, patrzysz na 10 000 wierszy wartości rozdzielonych przecinkami i zastanawiasz się: jak najszybciej przekonwertować CSV na JSON bez utraty danych?

Ten przewodnik obejmuje cztery metody konwersji (narzędzia w przeglądarce, JavaScript, Python, CLI), kierunek odwrotny (JSON na CSV), pięć pułapek, które po cichu psują dane, oraz sposób obsługi plików zbyt dużych, by zmieścić je w pamięci.

CSV a JSON: kiedy użyć którego

Zanim przystąpisz do konwersji, warto zrozumieć, w czym każdy z formatów jest dobry.

WymiarCSVJSON
StrukturaPłaska tabela (wiersze i kolumny)Zagnieżdżona hierarchia (obiekty, tablice)
Typy danychWszystko jest łańcuchem znakówstring, number, boolean, null
Czytelność dla człowiekaPrzyjazny dla arkuszy kalkulacyjnychPrzyjazny dla deweloperów
Główne zastosowanieEksport/import danych, raporty, ETLAPI, pliki konfiguracyjne, magazyny NoSQL
Rozmiar plikuMniejszy (brak powtarzanych nazw kluczy)Większy (nazwy kluczy powtarzają się dla każdego rekordu)
SchematDomyślny (wiersz nagłówkowy)Jawny (lub poprzez JSON Schema)

Reguła kciuka: wybierz CSV, gdy dane są tabelaryczne, a odbiorcą jest arkusz kalkulacyjny lub potok danych. Wybierz JSON, gdy dane mają hierarchię lub gdy odbiorcą jest API. Wynikowy JSON warto zweryfikować w narzędziu Formatowanie JSON, aby wcześnie wychwycić problemy strukturalne.

Jeśli w projekcie używasz luźniejszych formatów typu JSON5 lub JSONC do konfiguracji, zajrzyj do naszego przewodnika po JSON5 i JSONC, gdzie omawiamy różnice składniowe i narzędzia.

4 sposoby konwersji CSV na JSON

Metoda 1 — narzędzie w przeglądarce

Do jednorazowych konwersji najszybsza ścieżka prowadzi przez przeglądarkę. Wklej CSV do konwertera online, odbierz JSON, a następnie zweryfikuj wynik w narzędziu Formatowanie JSON, aby potwierdzić poprawność struktury.

Przewaga jest jasna: dane nigdy nie opuszczają przeglądarki. Żadnych uploadów, żadnego przetwarzania po stronie serwera, żadnych obaw o prywatność. Ma to znaczenie przy danych wewnętrznych, kluczach API osadzonych w eksportach lub czymkolwiek, czego nie chcesz wysyłać na zewnętrzny serwer.

Najlepsze do: małych plików (poniżej 10 MB), szybkich konwersji ad hoc oraz członków zespołu nietechnicznych.

Metoda 2 — JavaScript / Node.js

Przeglądarka (czysty JS):

function csvToJson(csv) {
  const lines = csv.trim().split('\n');
  const headers = lines[0].split(',').map(h => h.trim());

  return lines.slice(1).map(line => {
    const values = line.split(',');
    return headers.reduce((obj, header, i) => {
      obj[header] = values[i]?.trim() ?? '';
      return obj;
    }, {});
  });
}

const csv = `name,age,city
Alice,30,New York
Bob,25,London`;

console.log(JSON.stringify(csvToJson(csv), null, 2));

To rozwiązanie sprawdzi się dla prostego CSV bez pól w cudzysłowach. Do zastosowań produkcyjnych — z przecinkami w wartościach, znakami nowej linii w polach lub łańcuchami w cudzysłowach — należy użyć właściwego parsera.

Node.js (csv-parser + strumienie):

import { createReadStream } from 'fs';
import { parse } from 'csv-parse';

const records = [];

createReadStream('data.csv')
  .pipe(parse({ columns: true, trim: true, skip_empty_lines: true }))
  .on('data', (row) => records.push(row))
  .on('end', () => {
    console.log(JSON.stringify(records, null, 2));
  });

Opcja columns: true traktuje pierwszy wiersz jako klucze. Opcja trim usuwa białe znaki z wartości. Takie podejście poprawnie obsługuje pola w cudzysłowach, ucieczki przecinków oraz wartości wielowierszowe.

Metoda 3 — Python

Biblioteka standardowa (zero zależności):

import csv
import json

with open('data.csv', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    rows = list(reader)

with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(rows, f, indent=2, ensure_ascii=False)

csv.DictReader zamienia każdy wiersz w słownik, używając wiersza nagłówkowego jako kluczy. Flaga ensure_ascii=False zachowuje znaki Unicode (chińskie, japońskie, znaki diakrytyczne) zamiast escapować je do postaci \uXXXX.

Pandas (jednolinijkowiec dla data scientistów):

import pandas as pd

df = pd.read_csv('data.csv')
df.to_json('data.json', orient='records', indent=2, force_ascii=False)

Kiedy co wybrać:

  • csv + json: lekkie skrypty, funkcje Lambda, kontenery — wszędzie tam, gdzie zależy Ci na minimalnych zależnościach.
  • pandas: gdy oprócz konwersji chcesz oczyścić, przefiltrować lub przekształcić dane. Narzut importu pandas zwraca się z nawiązką, jeśli robisz coś więcej niż samą konwersję formatu.

Metoda 4 — narzędzia CLI

Do skryptów powłoki i potoków automatyzacji:

csvkit:

# Install: pip install csvkit
csvjson data.csv > data.json

Miller (mlr):

# Install: brew install miller (macOS) lub apt install miller (Ubuntu)
mlr --csv --json cat data.csv > data.json

Potok z jq do filtrowania:

# Convert and filter in one pipeline
csvjson data.csv | jq '[.[] | select(.age | tonumber > 25)]'

Miller jest szczególnie potężny, ponieważ natywnie obsługuje CSV, JSON, TSV i inne formaty. Dane można przekształcać w trakcie konwersji:

# Convert CSV to JSON, rename a field, add a computed field
mlr --csv --json rename name,fullName then put '$age_group = ($age > 30) ? "senior" : "junior"' data.csv

JSON na CSV: kierunek odwrotny

Konwersja JSON na CSV niesie ze sobą wyzwania, które nie istnieją w kierunku „w przód”.

Spłaszczanie zagnieżdżonych obiektów

CSV jest z natury płaski. Gdy JSON zawiera zagnieżdżone obiekty, potrzebujesz strategii spłaszczania:

{
  "name": "Alice",
  "address": {
    "city": "New York",
    "zip": "10001"
  }
}

Staje się:

nameaddress.cityaddress.zip
AliceNew York10001

Konwencja notacji kropkowej (address.city) to najczęstsze rozwiązanie. W Pythonie:

import pandas as pd

data = [
    {"name": "Alice", "address": {"city": "New York", "zip": "10001"}},
    {"name": "Bob", "address": {"city": "London", "zip": "EC1A"}}
]

df = pd.json_normalize(data)
df.to_csv('output.csv', index=False)
# Columns: name, address.city, address.zip

Obsługa tablic

Pola tablicowe wymagają decyzji:

StrategiaPrzykład wejściaWynik CSVNajlepsze do
Złączenie w łańcuch["admin","editor"]admin;editorProste listy, możliwość ponownego importu
Rozwinięcie do kolumn["admin","editor"]role_0: admin, role_1: editorTablice o stałej długości
Rozwinięcie do wierszy["admin","editor"]Dwa wiersze, po jednym na rolęAnaliza relacyjna

Wybierz odpowiednio do dalszego odbiorcy. Jeśli CSV trafia z powrotem do bazy danych, najczęściej najlepiej sprawdza się rozwinięcie do wierszy.

Utrata informacji o typach

CSV nie ma żadnego systemu typów. Po konwersji JSON na CSV:

  • true staje się łańcuchem "true" — boolean czy łańcuch?
  • null staje się pustą komórką — nieodróżnialną od pustego łańcucha "".
  • 42 staje się "42" — liczba czy łańcuch?

Jeśli wierność rundy (CSV → przetwarzanie → JSON) jest istotna, udokumentuj konwencje typów w komentarzu nagłówkowym lub w towarzyszącym pliku schematu.

5 typowych pułapek i jak ich uniknąć

Te problemy po cichu psują dane. Większość samouczków je pomija. Nie ucz się ich na produkcji.

1. Miny w kodowaniu

Problem: otwierasz CSV od kolegi i widzisz é zamiast é lub 锟斤拷 zamiast chińskich znaków.

Dlaczego się dzieje: plik został zapisany w jednym kodowaniu (Windows-1252, GBK, Shift_JIS), ale parser zakłada UTF-8. Excel pod Windows często zapisuje CSV jako Windows-1252 albo dodaje znacznik UTF-8 BOM (Byte Order Mark — niewidzialne \xEF\xBB\xBF na początku pliku).

Rozwiązanie:

# Detect encoding first
import chardet

with open('data.csv', 'rb') as f:
    result = chardet.detect(f.read(10000))
    print(result)  # {'encoding': 'Windows-1252', 'confidence': 0.73}

# Then read with the correct encoding
with open('data.csv', encoding=result['encoding']) as f:
    reader = csv.DictReader(f)
    # ...

W Node.js usuń BOM jawnie:

import { readFileSync } from 'fs';

let content = readFileSync('data.csv', 'utf-8');
// Strip UTF-8 BOM if present
if (content.charCodeAt(0) === 0xFEFF) {
  content = content.slice(1);
}

2. Pomyłka separatorów

Problem: parser produkuje jedną gigantyczną kolumnę zamiast wielu pól.

Dlaczego się dzieje: w wielu lokalizacjach europejskich (Francja, Niemcy, Hiszpania) Excel używa średnika (;) jako separatora pól w CSV, ponieważ przecinek pełni funkcję separatora dziesiętnego (np. 3,14 zamiast 3.14). Pliki rozdzielone tabulatorem (.tsv) to kolejny wariant.

Rozwiązanie: automatycznie wykrywaj separator, próbkując kilka pierwszych wierszy:

import csv

with open('data.csv') as f:
    sample = f.read(8192)
    dialect = csv.Sniffer().sniff(sample, delimiters=',;\t|')
    f.seek(0)
    reader = csv.DictReader(f, dialect=dialect)

3. Znikające zera wiodące

Problem: kod pocztowy 00501 staje się 501. Kod produktu 007 zmienia się w 7.

Dlaczego się dzieje: parser (lub Excel) interpretuje pole jako liczbę i obcina zera wiodące. Jest to szczególnie groźne dla kodów pocztowych, numerów telefonu i identyfikatorów.

Rozwiązanie: wymuś typ łańcuchowy. W pandas:

df = pd.read_csv('data.csv', dtype={'zip': str, 'product_code': str})

W JavaScripcie sprawdź, czy oryginalny łańcuch różni się od wyniku parsowania liczbowego:

function preserveLeadingZeros(value) {
  if (/^0\d+$/.test(value)) return value; // Keep as string
  const num = Number(value);
  return isNaN(num) ? value : num;
}

4. Utrata precyzji dużych liczb

Problem: identyfikator 9007199254740993 staje się 9007199254740992 w wynikowym JSON.

Dlaczego się dzieje: typ Number w JavaScripcie to 64-bitowy float (IEEE 754). Liczby całkowite większe niż Number.MAX_SAFE_INTEGER (2^53 − 1 = 9007199254740991) tracą precyzję. Dotyczy to identyfikatorów baz danych, identyfikatorów Snowflake oraz identyfikatorów postów Twittera/X.

Rozwiązanie: trzymaj duże liczby w JSON jako łańcuchy lub używaj BigInt w kodzie przetwarzającym:

// Parse with string preservation for large numbers
function safeParseNumber(value) {
  const num = Number(value);
  if (Number.isInteger(num) && !Number.isSafeInteger(num)) {
    return value; // Keep as string to preserve precision
  }
  return isNaN(num) ? value : num;
}

5. Niejednoznaczność wartości pustych

Problem: plik CSV zawiera puste komórki. Po konwersji nie wiadomo, czy oryginalna wartość była pustym łańcuchem "", null, czy po prostu brakowało jej w danych.

Dlaczego się dzieje: CSV nie ma sposobu rozróżnienia tych trzech stanów. Puste pole pomiędzy dwoma przecinkami (Alice,,30) może oznaczać dowolny z nich.

Rozwiązanie: zdefiniuj konwencję i stosuj ją konsekwentnie:

def parse_value(value):
    if value == '':
        return None        # or '' — pick one convention
    if value == 'NULL' or value == 'null':
        return None
    return value

Jeśli w danych występują wartości specjalne typu NULL, N/A lub -, udokumentuj je i obsłuż jawnie.

Strumieniowanie dużych plików

Gdy CSV przekracza 100 MB, ładowanie całości do pamięci przestaje wchodzić w grę. Skorzystaj ze strumieniowania.

Node.js (potok strumieni):

import { createReadStream, createWriteStream } from 'fs';
import { parse } from 'csv-parse';
import { Transform } from 'stream';
import { pipeline } from 'stream/promises';

let first = true;
const toJsonArray = new Transform({
  objectMode: true,
  transform(record, encoding, callback) {
    const prefix = first ? '[\n' : ',\n';
    first = false;
    callback(null, prefix + JSON.stringify(record));
  },
  flush(callback) {
    callback(null, '\n]');
  }
});

await pipeline(
  createReadStream('large.csv'),
  parse({ columns: true, trim: true }),
  toJsonArray,
  createWriteStream('large.json')
);

Python (generator):

import csv
import json

def csv_rows(path):
    with open(path, encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            yield row

# Stream to JSON Lines format (one JSON object per line)
with open('large.jsonl', 'w', encoding='utf-8') as out:
    for row in csv_rows('large.csv'):
        out.write(json.dumps(row, ensure_ascii=False) + '\n')

W przypadku bardzo dużych plików rozważ format JSON Lines (.jsonl) zamiast pojedynczej tablicy JSON. Każda linia jest niezależnym obiektem JSON, dzięki czemu wynikowy plik możesz przetwarzać linia po linii — bez konieczności parsowania całości naraz.

FAQ

Jaka jest różnica między CSV a JSON?

CSV (Comma-Separated Values) przechowuje dane w postaci płaskiej tabeli, w której każda wartość jest łańcuchem znaków. JSON (JavaScript Object Notation) zapisuje dane strukturalne z zagnieżdżonymi obiektami, tablicami oraz wartościami z typami (łańcuchami, liczbami, wartościami logicznymi, null). CSV jest mniejszy i przyjazny arkuszom kalkulacyjnym; JSON jest bardziej wyrazisty i przyjazny API.

Jak przekonwertować CSV na JSON w JavaScripcie?

W Node.js użyj pakietu csv-parse: odczytaj plik przez createReadStream, przepuść przez parse({ columns: true }) i zbierz wyniki. W przeglądarce odczytaj plik za pomocą FileReader, podziel po znakach nowej linii i przyporządkuj wiersze do obiektów, wykorzystując wiersz nagłówkowy jako klucze.

Jak przekonwertować CSV na JSON w Pythonie?

Użyj csv.DictReader z biblioteki standardowej, aby odczytać wiersze jako słowniki, a następnie json.dump(), aby zapisać je jako tablicę JSON. Do manipulacji danymi przed konwersją alternatywą jest jednolinijkowiec: pandas.read_csv() plus df.to_json(orient='records').

Czy zagnieżdżony JSON da się przekonwertować na CSV?

Tak, ale potrzebujesz strategii spłaszczania. Najpopularniejsze podejście używa notacji kropkowej: pole takie jak address.city staje się nagłówkiem kolumny. W Pythonie obsługuje to automatycznie pandas.json_normalize(). Tablice wymagają dodatkowych decyzji — złączyć je w łańcuchy, rozwinąć do kolumn lub rozwinąć do wierszy.

Dlaczego po konwersji w moim CSV są krzaczki?

Niezgodność kodowania. Plik najprawdopodobniej został zapisany w Windows-1252 lub GBK, podczas gdy parser zakłada UTF-8. Użyj biblioteki wykrywającej kodowanie, na przykład chardet (Python), aby zidentyfikować kodowanie, a następnie podaj je jawnie przy odczycie. Sprawdź też, czy plik nie zaczyna się od UTF-8 BOM, które niektóre narzędzia dodają automatycznie.

Jak obsłużyć plik CSV większy niż 100 MB?

Użyj strumieniowania zamiast ładować cały plik do pamięci. W Node.js przepuść dane przez csv-parse ze strumieniami. W Pythonie iteruj przez csv.DictReader z generatorem. Rozważ wynik w formacie JSON Lines (.jsonl) zamiast pojedynczej tablicy JSON — ułatwia to dalsze przetwarzanie.

Jak zweryfikować, że wynikowy JSON jest poprawny?

Wklej wynik do narzędzia online Formatowanie JSON, aby sprawdzić składnię, strukturę i zagnieżdżenie. Do automatycznej walidacji użyj JSON.parse() w JavaScripcie lub json.loads() w Pythonie — oba zgłaszają czytelne błędy dla nieprawidłowego wejścia. Do walidacji schematu zdefiniuj JSON Schema i waliduj programowo.

Najważniejsze wnioski

  1. Wybierz odpowiednią metodę do kontekstu: narzędzia w przeglądarce do szybkich przypadków ad hoc, kod do automatyzacji, CLI do potoków.
  2. Uważaj na problemy z kodowaniem — zawsze podawaj kodowanie jawnie, zamiast polegać na wartościach domyślnych.
  3. Zachowuj typy świadomie — zera wiodące, duże liczby całkowite oraz wartości null wymagają jawnej obsługi.
  4. Strumieniuj duże pliki zamiast ładować je do pamięci. Dla bardzo dużych zbiorów rozważ format JSON Lines.
  5. Waliduj wynik — przepuść skonwertowany JSON przez Formatowanie JSON, aby wychwycić problemy strukturalne, zanim trafią na produkcję.

Powiązane artykuły

Zobacz wszystkie artykuły