3. blokk · Modern JS · 11. fejezet
Egy szerver szövegként kap és küld adatot — ezt a szöveget hívják JSON-nak, és a
JSON.stringify / JSON.parse páros fordít oda-vissza. Mellé
megismersz két új gyűjteményt (Map, Set), amelyek bizonyos helyzetekben jobbak az
objektumnál és a tömbnél, és rendbe tesszük a Date és a Math leggyakoribb használatát.
A JSON (JavaScript Object Notation) egy szöveges adatformátum: így néz ki egy objektum, amikor fájlba írjuk vagy hálózaton elküldjük. A szintaxisa a JS-objektumból nőtt ki, ezért ismerős lesz — de szigorúbb:
// JSON-szöveg (pontosan így, idézőjeles kulcsokkal): { "nev": "Egér", "ar": 6990, "raktaron": true, "cimkek": ["usb", "vezeték nélküli"], "szallito": { "nev": "GLS", "napok": 2 }, "megjegyzes": null }
| Szabály | JS-objektumban | JSON-ban |
|---|---|---|
| Kulcsok | nev: 1 — idézőjel nélkül is jó | "nev": 1 — mindig dupla idézőjelben |
| Szövegek | 'a', "a", `a` | csak "a" (dupla idézőjel) |
| Megengedett értékek | bármi, függvény is | szöveg, szám, true/false, null, tömb, objektum |
undefined, függvény, Date | lehet | nincs — kimarad, ill. a Date szöveggé alakul |
| Komment, záró vessző | lehet | nincs — hibát okoz |
Fontos különbség fejben: a JSON szöveg (egy string), az objektum pedig
élő adat a memóriában, amin pont-jelöléssel dolgozunk. A két irány közötti fordítás a JSON
beépített objektum két metódusa.
Mindenhol. Egy Express-végpontban a res.json(adat) a háttérben JSON.stringify-t
hív, és a kapott szöveget küldi el a kliensnek; a bejövő kérés törzsét az express.json() middleware
JSON.parse-olja, hogy req.body-ban már objektumot kapj. A projekt konfigurációja
(package.json, beállításfájlok) szintén JSON — ezért kell ismerned a szigorú szintaxist.
A JSON.stringify(ertek) bármilyen objektumot vagy tömböt egysoros JSON-szöveggé alakít:
const termek = { nev: "Egér", ar: 6990, cimkek: ["usb"] }; const szoveg = JSON.stringify(termek); console.log(szoveg); // {"nev":"Egér","ar":6990,"cimkek":["usb"]} console.log(typeof szoveg); // string
Fájlba íráshoz vagy hibakereséshez olvasható, többsoros alak kell. A második paraméter egy szűrő (most null),
a harmadik a behúzás szóközeinek száma:
console.log(JSON.stringify(termek, null, 2)); // { // "nev": "Egér", // "ar": 6990, // "cimkek": [ // "usb" // ] // }
Amit a JSON nem tud ábrázolni, azt a stringify csendben kihagyja vagy átalakítja:
const o = { nev: "Egér", ar: undefined, // kimarad brutto() { return 1; }, // függvény: kimarad megjegyzes: null, // marad: null érvényes JSON letrehozva: new Date(2026, 8, 7) // szöveggé alakul (ISO-alak) }; console.log(JSON.stringify(o)); // {"nev":"Egér","megjegyzes":null,"letrehozva":"2026-09-06T22:00:00.000Z"}
Ha egy Date-et JSON-ba írsz, majd visszaolvasod, szöveget kapsz, nem Date-et.
Ha dátumként kell, csomagold vissza: new Date(adat.letrehozva).
A JSON.parse(szoveg) a fordított irány: JSON-szövegből élő objektumot (vagy tömböt, számot…) csinál:
const szoveg = '{"nev":"Egér","ar":6990,"cimkek":["usb"]}'; const termek = JSON.parse(szoveg); console.log(termek.nev); // Egér console.log(termek.cimkek[0]); // usb console.log(termek.ar * 2); // 13980 — már szám, nem szöveg
Ha a szöveg nem érvényes JSON (elgépelt idézőjel, záró vessző, komment), a JSON.parse
SyntaxError-t dob, és a program leáll. Hálózatról vagy fájlból jövő adatnál ez bármikor előfordulhat —
a 13. fejezetben a try / catch-csel fogjuk védeni.
A 9. fejezetből tudod: a { ...obj } sekély másolat — a beágyazott objektumok
közösek maradnak. Egy gyors mély másolat: oda-vissza fordítás JSON-on keresztül.
const rendeles = { azonosito: 1, cim: { varos: "Pécs" } }; const sekely = { ...rendeles }; sekely.cim.varos = "Győr"; console.log(rendeles.cim.varos); // Győr — az eredeti is változott! const mely = JSON.parse(JSON.stringify(rendeles)); mely.cim.varos = "Szeged"; console.log(rendeles.cim.varos); // Győr — az eredeti érintetlen
Korlátai ugyanazok, mint a JSON-nak: a függvények, az undefined értékek elvesznek, a Date
szöveggé válik, a Map/Set üres objektum lesz. Sima adatobjektumokra (amit egy API is
visszaadna) viszont tökéletes. (Modern környezetben van structuredClone(obj) is, amely ezeket is kezeli.)
Az objektum is kulcs–érték tár, de a kulcsa mindig szöveg lesz, és nincs egyszerű módja megszámolni, hány elem van
benne. A Map egy kifejezetten erre tervezett gyűjtemény:
const keszlet = new Map(); keszlet.set("Egér", 3); // beszúrás / felülírás keszlet.set("Kábel", 12); keszlet.set("Egér", 5); // ugyanaz a kulcs → felülírja console.log(keszlet.get("Egér")); // 5 console.log(keszlet.get("Monitor")); // undefined — nincs ilyen kulcs console.log(keszlet.has("Kábel")); // true console.log(keszlet.size); // 2 keszlet.delete("Kábel"); console.log(keszlet.size); // 1
| Művelet | Objektum | Map |
|---|---|---|
| beszúrás | o[k] = v | m.set(k, v) |
| olvasás | o[k] | m.get(k) |
| van-e | k in o | m.has(k) |
| törlés | delete o[k] | m.delete(k) |
| elemszám | Object.keys(o).length | m.size |
| kulcs típusa | csak szöveg (számból is szöveg lesz) | bármi: szám, objektum, logikai… |
| sorrend | általában beszúrási, de vannak kivételek | garantáltan beszúrási |
A for…of a Map-en [kulcs, érték] párokat ad — a 9. fejezet tömb-destrukturálása pont ide való:
for (const [nev, db] of keszlet) { console.log(`${nev}: ${db} db`); } console.log([...keszlet.keys()]); // [ 'Egér' ] console.log([...keszlet.values()]); // [ 5 ]
Az Object.entries ugyanilyen párok tömbjét adja, a Map konstruktora pedig pont ilyet vár — és
visszafelé az Object.fromEntries egy Map-ből (vagy párokból) objektumot épít:
const obj = { a: 1, b: 2 }; const m = new Map(Object.entries(obj)); // Map(2) { 'a' => 1, 'b' => 2 } const vissza = Object.fromEntries(m); // { a: 1, b: 2 }
Objektum: ha egy „dolgot" írsz le rögzített mezőkkel (termék: név, ár, készlet) — ez megy JSON-ba is.
Map: ha egy szótárat építesz futás közben, sok, előre nem ismert kulccsal (számlálás, gyorsítótár,
azonosító → rekord), vagy ha a kulcs nem szöveg. A Map nem megy közvetlenül JSON-ba — előtte
Object.fromEntries vagy [...m].
A Set olyan gyűjtemény, amelyben minden érték legfeljebb egyszer szerepel. Ha kétszer adod
hozzá ugyanazt, egyszerűen nem történik semmi:
const cimkek = new Set(); cimkek.add("usb"); cimkek.add("gamer"); cimkek.add("usb"); // már benne van → nem változik console.log(cimkek.size); // 2 console.log(cimkek.has("gamer")); // true cimkek.delete("gamer"); console.log([...cimkek]); // [ 'usb' ]
Tömb → Set → tömb. A Set eldobja az ismétlődéseket, és megőrzi az első előfordulás sorrendjét; a spread pedig visszaalakítja tömbbé:
const rendelesek = ["Egér", "Kábel", "Egér", "Monitor", "Kábel"]; const egyedi = [...new Set(rendelesek)]; console.log(egyedi); // [ 'Egér', 'Kábel', 'Monitor' ] console.log(new Set(rendelesek).size); // 3 — hány különböző
A Set szigorú egyenlőséget (===) használ: a "1" és az 1 két külön érték,
és két külön { a: 1 } objektum is két elem (más a referenciájuk).
A Date egy időpontot tárol (ezredmásodperc-pontossággal). Létrehozás három gyakori módon:
const most = new Date(); // a jelen pillanat const a = new Date("2026-09-07"); // ISO-szövegből (éjfél, UTC) const b = new Date(2026, 8, 7, 14, 30); // év, hónap (0-tól!), nap, óra, perc
getMonth() januárra 0-t, szeptemberre 8-at ad, és a konstruktor
is így várja. Kiíráskor ezért + 1. A nap (getDate()) viszont 1-től megy,
a hét napja (getDay()) 0 = vasárnap, 1 = hétfő…
const d = new Date(2026, 8, 7); console.log(d.getFullYear()); // 2026 console.log(d.getMonth() + 1); // 9 console.log(d.getDate()); // 7 console.log(d.getDay()); // 1 (hétfő) console.log(d.getTime()); // 1788732000000 — ms 1970. jan. 1. óta (időbélyeg; magyar időzóna szerint) console.log(d.toISOString()); // 2026-09-06T22:00:00.000Z — UTC-ben, szövegként
function datumFormaz(d) { const ho = String(d.getMonth() + 1).padStart(2, "0"); const nap = String(d.getDate()).padStart(2, "0"); return `${d.getFullYear()}.${ho}.${nap}.`; } console.log(datumFormaz(new Date(2026, 8, 7))); // 2026.09.07.
Két Date kivonása az időbélyegek különbségét adja ezredmásodpercben; egy nap 86 400 000 ms:
const kezdet = new Date("2026-09-07"); const hatarido = new Date("2026-09-30"); const napok = Math.round((hatarido - kezdet) / 86400000); console.log(napok); // 23
Ennyi Date most elég: a komolyabb dátumkezelést (időzónák, formázás nyelv szerint) Node-ban jellemzően könyvtárral oldjuk meg.
A Math függvényeit már használtad; itt a leggyakoribbak egy helyen, plusz három hasznos minta.
| Függvény | Mit csinál | Példa |
|---|---|---|
Math.round | kerekítés a legközelebbi egészre | Math.round(2.5) → 3, Math.round(-2.7) → −3 |
Math.floor / ceil | lefelé / felfelé | Math.floor(2.9) → 2, Math.ceil(2.1) → 3 |
Math.trunc | levágja a törtrészt (0 felé) | Math.trunc(-2.7) → −2 |
Math.abs | abszolút érték | Math.abs(-5) → 5 |
Math.max / min | legnagyobb / legkisebb | Math.max(...[3, 9, 5]) → 9 |
Math.pow, **, sqrt, hypot | hatvány, gyök, távolság | 2 ** 10 → 1024, Math.hypot(3, 4) → 5 |
Math.random | véletlen [0, 1) | Math.random() → pl. 0.4271 |
// 1) kerekítés n tizedesre: felszorzás, kerekítés, visszaosztás function kerekit(x, tizedes) { const szorzo = 10 ** tizedes; return Math.round(x * szorzo) / szorzo; } console.log(kerekit(3.14159, 2)); // 3.14 // 2) határok közé szorítás (clamp) function kozepre(x, min, max) { return Math.min(Math.max(x, min), max); } console.log(kozepre(15, 0, 10)); // 10 // 3) egész véletlen [min, max] között (mindkét vég beleértve) function veletlen(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } console.log(veletlen(1, 6)); // 1..6 — kockadobás
0.1 + 0.2 nem pontosan 0.3, hanem 0.30000000000000004 — ez minden
nyelvben így van, a bináris ábrázolás miatt. Pénzt ezért egész fillérben/forintban tárolunk, vagy a
kiírás előtt kerekítünk (kerekit(x, 2) vagy x.toFixed(2), ami szöveget ad).
Fordíts oda-vissza JSON-t, tölts fel egy Map-et, szűrj Set-tel, formázz dátumot. A kimenet úgy jelenik meg, ahogy Node-ban a
console.log mutatná — a Map és a Set kiírása is a Node-os alak.
Válassz mintát vagy írj sajátot — majd Futtatás (Ctrl+Enter) ↓
Függvényeket írsz, amelyeket az ellenőrző különböző argumentumokkal hív meg, és a visszatérési értéket hasonlítja a várttal (objektumot, tömböt, Map-et is mélyen összevet). A Futtatás az első tesztesettel próbálja ki a kódod, az Ellenőrzés az összessel. Figyelj a pontos formátumokra: a JSON-szövegeknek karakterre egyezniük kell.
⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás — a haladásod ebben a böngészőben megmarad.
Nézd meg a „VÁRT" és a „KAPOTT" sort a teszt alatt. Szövegnél gyakori a hiányzó pont vagy szóköz; objektumnál egy plusz vagy hiányzó kulcs; Map-nél az, hogy objektumot adtál vissza Map helyett (vagy fordítva).
undefined/függvény; a Date szöveggé alakul.JSON.stringify(o) → egysoros szöveg; JSON.stringify(o, null, 2) → olvasható, tagolt alak.JSON.parse(szoveg) → objektum; hibás szövegre SyntaxError-t dob (→ 13. fejezet). A JSON.parse(JSON.stringify(o)) gyors mély másolat sima adatokra.set / get / has / delete / size, bármilyen kulcs, garantált sorrend, bejárás for (const [k, v] of m); new Map(Object.entries(o)) ↔ Object.fromEntries(m).add / has / delete / size; duplikátumszűrés: [...new Set(t)].new Date(), new Date("2026-09-07"), new Date(év, hónap0, nap); getMonth() 0-tól; getTime() időbélyeg; különbség napokban: Math.round((b - a) / 86400000).round / floor / ceil / trunc; kerekítés n tizedesre felszorzással; clamp Math.min(Math.max(x, min), max); egész véletlen Math.floor(Math.random() * (max - min + 1)) + min.Eddig objektumokat „kézzel" raktunk össze. A következő fejezetben az osztályokkal sablont adunk nekik: egy
class leírja, milyen mezői és metódusai vannak minden terméknek vagy rendelésnek, és
new-val annyit gyártunk belőle, amennyit akarunk — ez a Node-projektek service-rétegének alapja.