0%

📋 JSON – Datu apmaiņas formāts

JSON (JavaScript Object Notation) ir universāls teksta datu formāts, ko izmanto lietotnēs un API kā datu pārsūtīšanas standartu.

javascript

JSON sintakse

Teksts
// JSON ir tikai TEKSTS – pareiziem JSON formātam ir strikti noteikumi:
// ✅ Atslēgas OBLIGĀTI ar ""  (nevis single qoutes vai bez)
// ✅ Vērtības: string, number, boolean, null, array, object
// ❌ Nav komentāru, nav undefined, nav funkciju, nav Date

// Pareizs JSON:
const pareizs_json = `{
  "vārds": "Anna",
  "vecums": 28,
  "pilsēta": "Rīga",
  "aktīvs": true,
  "bilance": null,
  "telefoni": ["+371 12345678", "+371 87654321"],
  "adrese": {
    "iela": "Brīvības 1",
    "pasta_indekss": "LV-1001"
  }
}`;

// JSON datu tipi:
// "string"  → JavaScript string
// 123       → JavaScript number
// true      → JavaScript boolean
// null      → JavaScript null
// [...]     → JavaScript Array
// {...}     → JavaScript Object

// ❌ NEDRĪKST izmantot JSON:
// { vārds: "Anna" }            ← bez ""
// { "vārds": undefined }       ← undefined nav JSON
// { "datums": new Date() }     ← Date nav JSON
// { "fn": function(){} }       ← funkcija nav JSON

JSON.parse() un JSON.stringify()

Teksts
// ======================================
// JSON.parse() – teksts → JavaScript
// ======================================
const json_teksts = '{"vārds":"Anna","vecums":28,"aktīvs":true}';
const objekts = JSON.parse(json_teksts);

console.log(objekts.vārds);   // "Anna"
console.log(objekts.vecums);  // 28 (number, ne string!)
console.log(typeof objekts.vecums); // "number"

// Kļūdu apstrāde
try {
    const noformēts = JSON.parse("{nav: derīgs json}");
} catch (kļūda) {
    console.error("JSON kļūda:", kļūda.message);
}

// Atdzīvināšanas funkcija (reviver)
const ar_datumiern = JSON.parse(
    '{"vārds":"Anna","dzimšana":"1995-01-15"}',
    (atslēga, vērtība) => {
        if (atslēga === "dzimšana") return new Date(vērtība);
        return vērtība;
    }
);
console.log(ar_datumiern.dzimšana instanceof Date); // true

// ======================================
// JSON.stringify() – JavaScript → teksts
// ======================================
const dati = {
    vārds: "Anna",
    vecums: 28,
    hobiji: ["lasīšana", "sports"],
};

// Kompakts
const kompakts = JSON.stringify(dati);
// {"vārds":"Anna","vecums":28,"hobiji":["lasīšana","sports"]}

// Skaists (formatēts)
const skaists = JSON.stringify(dati, null, 2);
// {
//   "vārds": "Anna",
//   "vecums": 28,
//   ...
// }

// Atslēgu filtrēšana
const tikai_vārds = JSON.stringify(dati, ["vārds", "vecums"]);
// {"vārds":"Anna","vecums":28}

// JSON.stringify ignorē/komentē:
// undefined, Function, Symbol → izlaists
const ar_nederigu = { a: 1, b: undefined, c: function(){}, d: Symbol() };
JSON.stringify(ar_nederigu); // {"a":1}

Dziļa kopija ar JSON

Teksts
// ======================================
// Sekla kopija (shallow copy) – problēma
// ======================================
const oriģināls = { vārds: "Anna", adrese: { pilsēta: "Rīga" } };
const sekla = { ...oriģināls }; // Spread ir SEKLA kopija

sekla.vārds = "Jānis";
sekla.adrese.pilsēta = "Liepāja"; // Maina ORIĢINĀLĀ arī!

console.log(oriģināls.vārds);        // "Anna" (atsevišķs)
console.log(oriģināls.adrese.pilsēta); // "Liepāja" ← MAINĪTS!

// ======================================
// Dziļa kopija ar JSON (vienkārša metode)
// ======================================
const dziļa = JSON.parse(JSON.stringify(oriģināls));
dziļa.adrese.pilsēta = "Daugavpils";

console.log(oriģināls.adrese.pilsēta); // "Liepāja" (nemainīts)

// IEROBEŽOJUMI:
// ❌ Zaudē undefined, Function, Date, RegExp, Map, Set
const ar_datumu = { datums: new Date() };
const kopija = JSON.parse(JSON.stringify(ar_datumu));
console.log(kopija.datums instanceof Date); // false! (ir string)

// ======================================
// structuredClone() – Modernais veids (ES2022)
// ======================================
const oriģināls2 = { vārds: "Anna", datums: new Date(), masīvs: [1, 2, 3] };
const dziļa2 = structuredClone(oriģināls2);

dziļa2.masīvs.push(4);
console.log(oriģināls2.masīvs); // [1, 2, 3] nemainīts
console.log(dziļa2.datums instanceof Date); // true ← saglabā tipu!

JSON ar API – pilns piemērs

Teksts
// Klase API komunikācijai ar JSON
class API {
    #baseUrl;
    #galvenes;

    constructor(baseUrl, apiAtslēga = null) {
        this.#baseUrl = baseUrl.replace(/\/$/, "");
        this.#galvenes = {
            "Content-Type": "application/json",
            "Accept":        "application/json",
            ...(apiAtslēga && { "Authorization": `Bearer ${apiAtslēga}` }),
        };
    }

    async #pieprasīt(ceļš, iespējas = {}) {
        const atbilde = await fetch(`${this.#baseUrl}${ceļš}`, {
            ...iespējas,
            headers: { ...this.#galvenes, ...iespējas.headers },
        });

        const teksts = await atbilde.text();
        let dati;
        try {
            dati = teksts ? JSON.parse(teksts) : null;
        } catch {
            dati = teksts;
        }

        if (!atbilde.ok) {
            throw Object.assign(new Error(dati?.ziņa ?? "API kļūda"), {
                statuss: atbilde.status,
                dati,
            });
        }
        return dati;
    }

    get(ceļš)                { return this.#pieprasīt(ceļš); }
    post(ceļš, dati)         { return this.#pieprasīt(ceļš, { method: "POST",  body: JSON.stringify(dati) }); }
    put(ceļš, dati)          { return this.#pieprasīt(ceļš, { method: "PUT",   body: JSON.stringify(dati) }); }
    delete(ceļš)             { return this.#pieprasīt(ceļš, { method: "DELETE" }); }
}

// Izmantošana
const api = new API("https://jsonplaceholder.typicode.com");

try {
    const lietotājs = await api.get("/users/1");
    console.log("Iegūts:", lietotājs.name);

    const jauns = await api.post("/posts", {
        title: "Mans ieraksts",
        body: "Satura teksts",
        userId: 1,
    });
    console.log("Izveidots ID:", jauns.id);
} catch (kļūda) {
    console.error(`Kļūda ${kļūda.statuss}:`, kļūda.message);
}

JSON un localStorage

Teksts
// localStorage glabā tikai virknes – JSON palīdz glabāt objektus
const uzdevumi = [
    { id: 1, teksts: "Mācīties JS", pabeigts: false },
    { id: 2, teksts: "Lasīt grāmatu", pabeigts: true },
];

// ======================================
// Saglabāt
// ======================================
localStorage.setItem("uzdevumi", JSON.stringify(uzdevumi));

// ======================================
// Ielādēt
// ======================================
function iegūtUzdevumus() {
    const saglabātie = localStorage.getItem("uzdevumi");
    return saglabātie ? JSON.parse(saglabātie) : [];
}

const ielādētie = iegūtUzdevumus();
console.log(ielādētie[0].teksts); // "Mācīties JS"

// ======================================
// Drošs parsēšanas palīgs
// ======================================
function drošiParsēt(virkne, noklusējums = null) {
    try {
        return JSON.parse(virkne);
    } catch {
        return noklusējums;
    }
}

// ======================================
// Abstrahēta JSON localStorage klase
// ======================================
class KrātuvesVienums {
    constructor(atslēga) { this.atslēga = atslēga; }
    saglabāt(vērtība)  { localStorage.setItem(this.atslēga, JSON.stringify(vērtība)); }
    iegūt(nokl = null) { return drošiParsēt(localStorage.getItem(this.atslēga), nokl); }
    dzēst()            { localStorage.removeItem(this.atslēga); }
}

const uzdevumu_krātuve = new KrātuvesVienums("uzdevumi");
uzdevumu_krātuve.saglabāt(uzdevumi);
const atjauninātie = uzdevumu_krātuve.iegūt([]);

  <div class="sep-line"></div>
  <div class="highlight-box">
    <h4>🎉 Apsveicam! Jūs esat apguvuši visu kursu!</h4>
    <p>Tagad jums ir pamatzināšanas gan PHP, gan JavaScript programmēšanā. Turpiniet praktizēt un veidojiet savus projektus!</p>
  </div>