Jokainen projekti tarvitsee konfiguraation, ja sinulla on kolme päävaihtoehtoa: JSON, YAML tai TOML. Olen käyttänyt kaikkia kolmea laajasti, ja jokainen saa minut hulluksi eri tavoin. Tässä rehellinen arvioni siitä, milloin kannattaa käyttää mitäkin.
JSON: Yleissotilas
Tunnet JSON:in jo. Se on kaikkialla. Jokainen kieli osaa jäsentää sen. Mutta olkaamme rehellisiä sen heikkouksista konfiguraatiotiedostona:
- Ei kommentteja. Et kirjaimellisesti voi selittää, mitä asetus tekee. Se on hullua konfiguraatiotiedostolle.
- Ei lopun pilkkuja. Lisää uusi rivi loppuun, unohda pilkku edelliseltä riviltä — konfiguraatio rikki.
- Lainausmerkit kaikkialla. Jokainen avain tarvitsee kaksoislainausmerkit:
{"port": 8080}eikä vainport: 8080.
Tästä kaikesta huolimatta JSON:ia käytetään konfiguraatioon npm:ssä (package.json), TypeScriptissä (tsconfig.json), VS Codessa (settings.json) ja muualla. Syy? Nolla moniselitteisyyttä. JSON on niin tiukka, että on vain yksi tapa tulkita se.
YAML: Kaunis mutta vaarallinen
YAML näyttää upealta. Siisti, minimaalinen, ihmisluettava. Mutta sillä on joitain pahamaineisia ansoja:
Tämä on "Norja-ongelma", jonka mainitsin YAML-artikkelissa. YAML 1.1 käsittelee NO, YES, ON, OFF booleaneina. Se on korjattu YAML 1.2:ssa, mutta monet jäsentäjät käyttävät edelleen oletuksena 1.1-käyttäytymistä.
Sitten on sisennysherkkys. Yksi väärässä paikassa oleva välilyönti voi muuttaa tiedostosi merkityksen kokonaan — ja virheilmoitus on kauhea.
Siitä huolimatta YAML on standardi Docker Composelle, Kubernetesille, GitHub Actionsille ja Ansiblelle. Jos työskentelet DevOps/pilvi-alueella, YAML-osaaminen on pakollista.
TOML: Konfiguraation spesialisti
TOML (Tom's Obvious Minimal Language) suunniteltiin nimenomaan konfiguraatioon. Sen tavoitteena on olla ilmeinen — mikä tarkoittaa, että TOML-tiedostoa on (lähes) mahdoton lukea väärin.
Näin TOML-konfiguraatio näyttää:
Mitä TOML tekee todella hyvin: natiivit päivämäärä/aika-tyypit (created = 2026-03-08T10:30:00Z), ei sisennysongelmia, kommentit #-merkillä ja syntaksi, jota on aidosti vaikea sotkea.
Haittapuoli? Syvästi sisäkkäiset rakenteet muuttuvat monisanaisiksi. TOML on loistava tasaisille konfiguraatioille, mutta jos tarvitset viisi sisäkkäistasoa, YAML tai JSON voi olla luettavampaa.
TOML:ia käyttävät Rust (Cargo.toml), Python (pyproject.toml), Hugo ja kasvava joukko työkaluja.
Suositukseni
| Skenaario | Valinta | Miksi |
| Koneen generoima config | JSON | Tiukin ja yhteensopivin |
| DevOps/infrastruktuuri | YAML | Ekosysteemi odottaa sitä |
| Sovelluskonfiguraatio | TOML | Kommentit + minimaalinen moniselitteisyys |
| Yksinkertaiset avain-arvo-asetukset | TOML | Siistein tasaisille configeille |
| Monimutkaiset sisäkkäiset rakenteet | YAML | Paras sisäkkäissyntaksi |
Yhteenveto
Sama konfiguraatio kaikissa kolmessa formaatissa
Saman datan näkeminen kaikissa kolmessa formaatissa korostaa erot todella hyvin. Tässä on yksinkertainen sovelluskonfiguraatio:
JSON:
YAML:
TOML:
Huomaa, miten JSON vaatii kaikki nuo lainausmerkit ja aaltosulkeet, YAML on tiiviintä mutta nojaa sisennykseen, ja TOML löytää keskitien eksplisiittisillä osiotunnisteilla ja ilman sisennysriippuvuutta.
Yleisiä konfiguraatiotiedostovirheitä
YAML: Vahingollinen tyyppimuunnos. Norja-ongelman lisäksi YAML tulkitsee myös 3.10 numeroksi 3.1 (pudottaa perässä olevan nollan) ja 1_000 numeroksi 1000. Jos konfiguraatioarvosi ovat versiojonoja kuten 3.10, laita ne aina lainausmerkkeihin: version: "3.10".
JSON: Unohtaminen, ettei järjestyksellä ole väliä. JSON-objektit ovat järjestämättömiä spesifikaation mukaan. Jos konfiguraatiosi käsittely riippuu avainten järjestyksestä, rakennat hauraalle pohjalle. Jotkut jäsentäjät säilyttävät lisäysjärjestyksen, toiset eivät.
TOML: Sekaannus taulukkomäärien kanssa. TOML käyttää [[kaksoissulkeita]] taulukkotaulukoille, mikä hämmentää uusia käyttäjiä. Näin määrittelet useita palvelimia:
Ympäristökohtaiset konfiguraatiot
Alue, jolla kaikki kolme formaattia kamppailevat, on ympäristökohtaisten ohitusten käsittely (kehitys vs. staging vs. tuotanto). Yleisiä ratkaisuja ovat:
- Useita tiedostoja:
config.base.yaml+config.production.yamlsyväyhdistämisellä - Ympäristömuuttujien interpolointi: Jotkut YAML-työkalut tukevat
${DB_HOST}-syntaksia, mutta se ei ole standardi - Ulkoiset työkalut: Doppler, HashiCorp Vault tai pilvipohoiset konfiguraatiopalvelut
Henkilökohtaisesti suosin yksinkertaista lähestymistapaa: yksi konfiguraatiotiedosto järkevillä oletusarvoilla ja ympäristömuuttujat kaikelle, mikä muuttuu ympäristöjen välillä. Kaikki kolme formaattia voivat lukea ympäristömuuttujia sovellustasolla, joten konfiguraatioformaatin itsensä ei tarvitse tukea interpolointia.
Formaattien suosio ekosysteemeittäin
| Ekosysteemi | Ensisijainen formaatti | Tunnettuja esimerkkejä |
| JavaScript/Node.js | JSON | package.json, tsconfig.json, .eslintrc.json |
| Python | TOML | pyproject.toml, Cargo.toml (Rust) |
| DevOps/Cloud | YAML | docker-compose.yml, k8s-manifestit, GitHub Actions |
| Go | TOML/YAML | Molemmat laajasti käytössä, ei yhtä standardia |
| .NET | JSON | appsettings.json (korvasi XML-pohjaisen web.configin) |
Yhteenveto
Yhtä oikeaa vastausta ei ole. Käytä JSON:ia, kun tarvitset maksimaalisen yhteensopivuuden. Käytä YAML:ia, kun ekosysteemi vaatii sitä (Kubernetes ei ala hyväksyä TOML:ia). Käytä TOML:ia, kun haluat kommentteja ja minimaalisia yllätyksiä.
JSONC ja JSON5: JSON apupyörillä
Okei, olemme siis mollanneet JSON:ia kommenttien ja lopun pilkkujen puuttumisesta. Mutta tässä on asia, jota kukaan ei kerro sinulle: on olemassa JSON-variantteja, jotka korjaavat nämä ärsytykset, ja olet todennäköisesti käyttänyt yhtä niistä tietämättäsi.
Ensimmäisenä: JSONC (JSON with Comments). Jos olet koskaan avannut tsconfig.json-tiedoston ja ajatellut "hetkinen, täällä on kommentteja... luulin ettei JSON salli kommentteja?" — kyllä, se on JSONC. Se on periaatteessa JSON, mutta voit käyttää // yhden rivin kommentteja ja /* */ lohkokommentteja. VS Code käyttää JSONC:tä settings.json-, launch.json- ja keybindings.json-tiedostoilleen. TypeScriptin tsconfig.json on myös teknisesti JSONC, ei tiukkaa JSON:ia.
Näin JSONC näyttää:
Sitten on JSON5, joka menee pidemmälle. JSON5 höllentää monia JSON:in tiukimmista säännöistä:
- Yksinkertaiset lainausmerkit merkkijonoissa:
{'name': 'Sarah'}— vihdoinkin! - Lopun pilkut:
{"a": 1, "b": 2,}— ei enää diff-kohinaa - Lainausmerkkittömät avaimet (jos ne ovat kelvollisia tunnisteita):
{name: "Sarah"} - Heksadesimaalinumerot:
0xFF - Monirivise merkkijonot kenoviivan jatkolla
Infinity,-InfinityjaNaNkelvollisina numeroina
JSON5 on loistava konfiguraatiotiedostoille, joissa ihmiset ovat ensisijainen yleisö. Jotkut työkalut tukevat sitä natiivisti — esimerkiksi Babelin .babelrc voi olla JSON5. Mutta älä käytä JSON5:ttä API-vastauksiin tai tiedonvaihtoon. Tiukan JSON:in koko pointti on, että kaikki ovat samaa mieltä formaatista. JSON5 on ihmisille, ei koneille.
Nyrkkisääntöni: jos työkalu tukee JSONC:tä tai JSON5:ttä, käytä sitä. Kommenteista konfiguraatiotiedostoissa ei ole kirjaimellisesti mitään haittaa. Mutta jos kirjoitat kirjaston, joka lukee konfiguraatiota, tue ensin standardi-JSON:ia ja JSONC/JSON5:ttä valinnaisina lisäosina.
YAML-ankkurit ja aliakset: DRY-konfiguraatio
Tässä on YAML:in todellinen tappajominaisuus, jota monet kehittäjät eivät koskaan löydä: ankkurit ja aliakset. Niillä voit määritellä konfiguraatiolohkon kerran ja käyttää sitä uudelleen kaikkialla. Periaatteessa DRY (Don't Repeat Yourself) konfiguraatiotiedostoille.
Ankkuri merkitään &name:lla ja alias viittaa siihen *name:lla. Tässä käytännön Docker Compose -esimerkki:
Näitkö, mitä tapahtui? Määrittelimme yhteiset asetukset kerran &common:lla ja vedimme ne kolmeen palveluun <<: *common:lla. Ilman ankkureita kopioisit tuon uudelleenkäynnistyskäytännön ja lokikonfiguraation jokaiseen palveluun. Ja kun tarvitset muuttaa lokien kierrätystä? Yksi paikka kahdentoista sijaan.
Voit käyttää ankkureita myös yksinkertaisemmille arvoille — ei pelkästään mapeille:
Nyt sudenkuopat. Yhdistysavain <<, joka tekee ankkureista todella tehokkaita? Se ei ole oikeastaan osa YAML 1.2 -spesifikaatiota. Se oli YAML 1.1 -tyyppilaajennus, ja vaikka useimmat suositut jäsentäjät tukevat sitä edelleen, se on teknisesti epästandardi. Joten jos käytät tiukkaa YAML 1.2 -jäsentäjää, yhdistysavaimet eivät ehkä toimi.
Lisäksi ankkurit toimivat vain yhden tiedoston sisällä. Et voi viitata toisessa YAML-tiedostossa määriteltyyn ankkuriin. Ja virheilmoitukset, kun kirjoitat aliasnimen väärin? Yleensä jotain kuten "undefined alias" ilman mitään kontekstia siitä, missä ankkurin piti olla. Klassinen YAML.
TOML syväsukellus: Edistyneet ominaisuudet
Useimmat tuntevat TOML:in perusteet — osiot [sulkeilla], avain-arvo-parit, kommentit #:lla. Mutta TOML:issa on joitain todella hienoja ominaisuuksia, jotka eivät saa tarpeeksi huomiota. Käydään ne läpi.
Pistenotaatioavaimet mahdollistavat sisäkkäisten rakenteiden määrittelyn ilman osiotunnisteita:
Tämä on kätevää, kun sinulla on vain pari sisäkkäistä arvoa etkä halua luoda kokonaista osiota niille.
Rivinsisäiset taulukot tarjoavat JSON-tyylisen tiiviin syntaksin pienille objekteille:
Käytä rivinsisäisiä taulukoita säästeliäästi — ne eivät voi ulottua useille riveille ja muuttuvat lukukelvottomiksi nopeasti, jos tunget niihin liikaa.
Moniriviset merkkijonot tulevat kahdessa muodossa, ja tässä TOML on yllättävän harkittu:
Kolminkertaisesti lainattu perusmerkkijono (""") käsittelee pakotusjaksot, kun taas literaaliversio (''') käsittelee kaiken raakatekstinä. Tämä on täydellistä regex-kaavoille tai Windows-tiedostopoluille, joissa et halua kenoviivojen tulkittavan pakotusjaksoksi.
Natiivit päivämäärä/aika-tyypit ovat jotain, mitä JSON tai YAML ei käsittele näin siististi:
Nämä ovat ensiluokkaisia tyyppejä TOML:issa, eivät merkkijonoja, jotka esittävät päivämääriä. TOML-jäsentäjäsi antaa sinulle oikeita päivämäärä/aika-objekteja, ei merkkijonoja, jotka sinun pitää jäsentää itse.
Miksi Rustin Cargo valitsi TOML:in? Koska Cargo-konfiguraatiot ovat juuri TOML:in vahvuusaluetta: kohtuullisesti sisäkkäisiä, ihmisten muokkaamia, tarvitsevat kommentteja ja hyötyvät tiukasta tyypityksestä. Et halua riippuvuusversioidesi tulkittavan hiljaa liukuluvuiksi (katson sinua, YAML).
Turvallisuusnäkökohdat
Okei, tämä on osio, jossa asiat muuttuvat hieman pelottaviksi. Jos lataat konfiguraatiotiedostoja epäluotettavista lähteistä — tai vaikka luulisit, ettet tee niin — sinun pitää tietää deserialisointihyökkäyksistä.
Tämän paraatiesimerkki on PyYAML:in yaml.load(). Vanhemmissa versioissa tämä viattoman näköinen funktio pystyi suorittamaan mielivaltaista Python-koodia YAML-tiedostoon upotettuna. En vitsaile. Katso tätä:
Jos joku ujuttaa tämän YAML-konfiguraatioon ja Python-sovelluksesi lataa sen yaml.load():lla yaml.safe_load():n sijaan, se kirjaimellisesti suorittaa tuon järjestelmäkomennon. Poistaa kaiken. Asentaa takaoven. Mitä hyökkääjä haluaakin.
Korjaus on yksinkertainen — käytä aina yaml.safe_load():ia Pythonissa:
PyYAML-dokumentaatio varoittaa nyt tästä, ja uudemmat versiot näyttävät deprecation-varoituksen, jos käytät yaml.load():ia ilman Loaderin määrittelyä. Mutta lukemattomia tutoriaaleja ja Stack Overflow -vastauksia on edelleen, jotka näyttävät turvattoman version. Se on miina avoimesti näkyvillä.
Sitten on "billion laughs" -hyökkäys (tunnetaan myös XML-pommina, mutta toimii YAML:illakin). Ideana on rekursiivinen laajeneminen — määrittelet entiteettejä, jotka viittaavat muihin entiteetteihin, luoden eksponentiaalista kasvua:
Jokainen taso kertoo datan viidellä, joten tasolla 8 tai 9 katsot gigatavuja dataa muutamasta YAML-rivistä. Useimmilla moderneilla YAML-jäsentäjillä on syvyys- ja laajennusrajoituksia tämän estämiseksi, mutta siitä on hyvä tietää.
JSON on luonnostaan turvallisempi, koska sillä ei ole minkäänlaista suoritussemantiikkaa. Koodia ei voi upottaa, ei tyyppikonstruktoreita, ei entiteettilaajenusta. JSON-jäsentäjä vain lukee dataa — merkkijonoja, numeroita, booleaneja, taulukoita ja objekteja. Siinä kaikki. Tämä on yksi JSON:in yksinkertaisuuden aliarvostetuista eduista. Kun turvallisuudella on väliä, JSON:in ominaisuuksien puute on itse asiassa ominaisuus.
TOML on myös melko turvallinen — sillä ei ole koodinsuorituskykyjä eikä rekursiivista laajennusta. Mutta se on vähemmän taisteluteslattu kuin JSON-jäsentäjät, joten pidä TOML-kirjastosi ajan tasalla.
Yhteenveto: jos hyväksyt konfiguraatiotiedostoja käyttäjiltä tai ulkoisista lähteistä, JSON on turvallisin valinta. Jos sinun on käytettävä YAML:ia, käytä aina turvallisia latausfunktioita ja harkitse YAML-linterin ajamista epäilyttävien rakenteiden havaitsemiseksi.
Todellisia konfiguraatiotiedostoesimerkkejä
Teoria on hienoa, mutta katsotaan oikeita konfiguraatiotiedostoja, joita kohtaat luonnossa. Olen lisännyt huomautuksia jokaiseen korostaakseni formaattikohtaisia kuvioita.
GitHub Actions -työnkulku (YAML):
Tässä YAML todella loistaa. GitHub Actions -työnkulkusyntaksi olisi tuskallista JSON:issa — kaikki ne sisäkkäiset listat ja sisennysperustainen rakenne sopii luonnollisesti YAML:iin. Näet myös, miten kommentit auttavat selittämään matriisistrategiaa.
Rustin Cargo.toml (TOML):
Huomaa, miten Cargo-manifesti käyttää rivinsisäisiä taulukoita riippuvuuksille ominaisuuksineen. [[bin]] -kaksoissulkusyntaksi määrittelee taulukkomäärän — jokainen [[bin]]-merkintä lisää uuden binäärikohteen. TOML pitää tämän tasaisena ja luettavana ilman sisennyspelejä.
package.json (JSON):
Klassikko. Ei kommentteja, paljon lainausmerkkejä, mutta jokainen työkalu maapallolla osaa lukea sen. Mikä tekee package.json:ista toimivan JSON:in rajoituksista huolimatta, on se, että skeema on niin tunnettu — et tarvitse kommentteja selittämään, mitä scripts.build tekee, koska jokainen JavaScript-kehittäjä tietää sen jo.
.prettierrc (JSON):
Yksinkertainen, tasainen avain-arvo-konfiguraatio. Rehellisesti sanottuna tämä olisi hieman kivempi TOML:ina (kommentit!) tai jopa JSONC:nä, ja Prettier tukee muitakin formaatteja. Mutta JSON on oletus, ja näin yksinkertaiselle asialle sillä ei ole paljon väliä.
Siirtyminen formaattien välillä
Olet siis päättänyt, että projektisi konfiguraatioformaatti oli virhe ja haluat vaihtaa. Tai ehkä vedät konfiguraatiota työkalusta, joka käyttää eri formaattia. Joka tapauksessa sinun pitää muuntaa TOML:in, YAML:in ja JSON:in välillä. Kerron sinulle, se ei aina ole niin sujuvaa kuin toivoisit.
Muunnostyökalut:
- yq — YAML:in sveitsiläinen linkkuveitsi. Voi muuntaa YAML:in, JSON:in, TOML:in ja XML:n välillä.
yq -o=json config.yamlantaa JSON-tulosteen. Se on kuinjq, mutta YAML:ille. - toml-cli ja taplo — Komentorivi-TOML-prosessorit. Taplo on erityisen hyvä TOML:in muotoiluun ja validointiin.
- Python-yksirivit — Hätätilanteessa
python -c "import yaml, json, sys; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))" < config.yamlmuuntaa YAML:in JSON:iksi. Ei kaunis, mutta toimii. - Verkkomuuntimet — Nopeisiin kertaluonteisiin muunnoksiin formattimme voivat auttaa. Liitä konfiguraatiosi sopivaan formatteriin, siisti se ja kirjoita se manuaalisesti kohdeformaattiin.
Milloin siirtyä:
- Tiimisi tekee jatkuvasti YAML-sisennysvirheitä CI-konfiguraatioissa? Ehkä siirtyminen TOML:iin vähentää päänsärkyä.
- Tarvitset kommentteja JSON-konfiguraatiotiedostoon? Harkitse siirtymistä JSONC:hen (jos työkalu tukee) tai TOML:iin.
- Rakennat uutta Rust/Python-projektia ja ekosysteemi odottaa TOML:ia? Älä taistele vastaan — käytä TOML:ia.
Yleisiä sudenkuoppia siirtyessä:
YAML:in implisiittinen päivämääräjäsennys pistää sinua. Jos sinulla on YAML-arvo kuten release: 2024-03-08, YAML tulkitsee sen päivämääräobjektiksi, ei merkkijonoksi. Muunna se JSON:iksi ja saatat saada "release": "2024-03-08T00:00:00Z" tai "release": "2024-03-08" muuntimesta riippuen. Testaa tulostesi aina.
TOML:in tiukka tyypitys tarkoittaa, ettei sinulla voi olla sekatyyppisiä taulukoita. JSON:issa ja YAML:issa [1, "two", true] on täysin kunnossa. TOML:issa jokaisen taulukon elementin pitää olla samaa tyyppiä. Jos lähdedatassasi on sekatyyppisiä taulukoita, sinun pitää uudelleenrakentaa.
Ja tässä on iso juttu: kommentit häviävät. JSON ei tue kommentteja, joten jos muunnat TOML:ista tai YAML:ista JSON:iin, kaikki huolellisesti kirjoitetut kommenttisi katoavat. Toiseen suuntaan (JSON:ista YAML:iin/TOML:iin) haluat manuaalisesti lisätä kommentteja selittämään ei-ilmeisiä asetuksia, koska JSON-versiossa niitä varmasti ei ollut.
Vielä yksi asia — YAML:in ankkureilla ja aliaksilla ei ole vastineita JSON:issa tai TOML:issa. Jos YAML-konfiguraatiosi nojaa ankkureihin DRY-konfiguraatiolle, toiseen formaattiin muuntaminen tarkoittaa, että sinun pitää manuaalisesti kopioida nuo jaetut lohkot. Se voi olla merkittävä laajentuminen tiedostokoossa monimutkaisille konfiguraatioille.
Kokeile itse
Minkä formaatin valitsetkin, konfiguraatioiden pitäminen hyvin muotoiltuina tekee niistä helpompia tarkistaa ja debugata. TOML Formatter -työkalumme siivoaa sotkuiset TOML-tiedostot hetkessä. YAML Formatter korjaa sisennysongelmat ennen kuin ne aiheuttavat ongelmia. Ja JSON Formatter tekee syvästi sisäkkäisistäkin JSON-konfiguraatioista luettavia yhdellä silmäyksellä.