JSON Failide käsitlemine

Mis on JSON?

JSON ehk "JavaScript Object Notation" on tekstiformaat, mida kasutatakse andmevahetuseks ja -salvestuseks. JSON-i eelisteks on tema kerge loetavus ja arusaadavus nii inimestele (kerge lugeda/kirjutada) kui ka masinatele (kerge tõlgendada/genereerida).

JSON koosneb võtme-väärtus paaridest ja järjestatud järjenditest.

Kui olete tuttav Python programmerimiskeelega, siis JSON-i vorm võib meenutada sõnastikku:

{
    "key": "value",
    "anotherKey": 123,
    "list": ["a", "b", "c"],
    "valid": true,
    "objectInAnObject": {
        "key-ception": "value",
        "randomNumber": 1337
    },
    "reference": null
}

Logelised sulud tähistavad objekti. Võti on sõne, väärtus võib olla nii sõne, number, järjend, tõeväärtus, objekt või null. Järjend võib omaette samamoodi koosneda nii sõnedest, numbritest, teistest järjenditest, tõeväärtustest, objektidest või nullidest.

[{"result":"foo"}, {"result":"bar"}, {"result":"foobar"}]

JSON Javas

Javas JSONi töötlemiseks peame kasutama väliseid teeke. Mõned näited nendest oleksid: org.json, json-simple ja gson.

Gson

Gson on Google poolt loodud avatud lähtekoodiga teek JSON failide käsitlemiseks. Gsoni eelisteks on tema kerge kasutatavus ja kiirus.

Gson on saadaval siit: https://mvnrepository.com/artifact/com.google.code.gson/gson

Lähtekood on saadaval siit: https://github.com/google/gson

Gsoni paigaldamisel tuleks lähtuda antud artiklile: Väliste teekide lisamine

Gson objekti loomine

Gson objekti saab kahel viisil luua.

Esimene viis, mis loob Gson-i tavakonfiguratsioonis.

import com.google.gson.Gson;

Gson gson = new Gson();

Tavakonfiguratsioon:

  • Genereerib väga kompaktse json-i, kaotades ebavajalikud tühikud ära. Builderis saab antud käitumist muuta kasutades GsonBuilder.setPrettyPrinting()

  • null-väljad kaotatakse ära, kuid mitte järjendites. Builderis saab antud käitumist muuta kasutades GsonBuilder.serializeNulls()

  • Staatilised väljad jäetakse serialiseerimisel ja deserialiseerimisel välja. Builderis saab antud käitumist muuta kasutades GsonBuilder.excludeFieldsWithModifiers()

  • Ajaformaat eirab millisekundeid. Builderis saab antud käitumist muuta kasutades GsonBuilder.setDateFormat()

  • Mõndadel asjadel oma vaikimisi viisid serialiseerimiseks/deserialiseerimiseks (nt: Enum, URL-id, ajad jne). Builderis saab neid muuta kasutades GsonBuilder.registerTypeAdapter()

  • Väljad nimetatakse camelCase reeglite järgi. Builderis saab antud käitumist muuta kasutades GsonBuilder.setFieldNamingPolicy()

  • @Expose ja @Since annotatsioone eiratakse. Builderis saab käitumist muuta kasutades GsonBuilder.excludeFieldsWithoutExposeAnnotation() ja GsonBuilder.setVersion()

Teine viis on kasutada GsonBuilderit, millega saad tavakonfiguratsiooni üle kirjutada:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

Gson gson = new GsonBuilder().setPrettyPrinting().create(); // Here we make it so output json is pretty to look at

Java objekti JSON-iks tegemine

Java objekti JSON-iks tegemisel tuleb kasutada loodud gsoni objekti ning sealt välja kutsuda toJson():

import com.google.gson.Gson;

record Person(String firstName, String lastName) {}

public class Example {
    public static void main(String[] args) {
        Gson gson = new Gson();
        Person person = new Person("Stu", "Dent");
        String json = gson.toJson(person);
        System.out.println(json); // should print out - {"firstName":"Stu","lastName":"Dent"}
    }
}

JSON-i Java objektiks tegemine

Sarnaselt saab JSON objekti teha Java objektiks, kasutades loodud gson objektist meetodit fromJson():

import com.google.gson.Gson;

record Person(String firstName, String lastName) {}

public class Example {
    public static void main(String[] args) {
        Gson gson = new Gson();
        String json = "{\"firstName\":\"Stu\",\"lastName\":\"Dent\"}";
        Person person = gson.fromJson(json, Person.class); // input string, class to build upon
        System.out.println(person); // Should print out - Person[firstName=Stu, lastName=Dent]
    }
}

Kui on soov sõnest teha JsonObject, siis tuleb teha järgnevalt:

import com.google.gson.Gson;

record Person(String firstName, String lastName) {}

public class Example {
    public static void main(String[] args) {
        Gson gson = new Gson();
        String json = "{\"firstName\":\"Stu\",\"lastName\":\"Dent\"}";
        JsonObject obj = gson.fromJson(json, JsonObject.class); // input string, class to build upon

        // Now we should have a JsonObject, that we can modify
    }
}

JsonParser

Gson-i JsonParser-it kasutatakse, et ehitada sisendist JSON objekt valmis. Saadud objektist on võimalik kätte saada erinevaid väärtusi ning neid muuta.

JsonParserit kasutatakse järgnevalt:

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public class Example {
    public static void main(String[] args) {
        String json = "{\"firstName\":\"Stu\",\"lastName\":\"Dent\"}";

        JsonElement element = JsonParser.parseString(json); // to parse input

        JsonObject obj = element.getAsJsonObject(); // to transform it into a json object. Same can be done with other datatypes (array, etc.)
    }
}

JsonElement on abstraktne klass, mille alam klassid on JsonObject, JsonArray jms.

JsonObject

JsonObject lubab meil loodud objekti lugeda ja muuta.

Lisame näiteks oma eelmises näites loodud inimesele emaili aadressi:

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

record Person(String firstName, String lastName) {}

public class Example {
    public static void main(String[] args) {
        String json = "{\"firstName\":\"Stu\",\"lastName\":\"Dent\"}";

        JsonElement element = JsonParser.parseString(json);
        JsonObject obj = element.getAsJsonObject();

        obj.addProperty("email", "student@taltech.ee"); // Adds a primitive field
        System.out.println(obj);    // {"firstName":"Stu","lastName":"Dent","email":"student@taltech.ee"}

        obj.add("school", new JsonObject());    // Adds JsonElements (JsonObject, JsonArray etc.), in this case we're adding another object
        System.out.println(obj);    // {"firstName":"Stu","lastName":"Dent","email":"student@taltech.ee","school":{}}

        obj.add("grades", new JsonArray()); // As an example, lets also add a JsonArray into the object
        System.out.println(obj);    // {"firstName":"Stu","lastName":"Dent","email":"student@taltech.ee","school":{},"grades":[]}
    }
}

Sama meetodit saame kasutada ka olemasolevate väljade uuendamiseks:

obj.addProperty("firstName", "Juulius");    // updates existsting field
System.out.println(obj);    // {"firstName":"Juulius","lastName":"Dent","email":"student@taltech.ee"}

Olemasolevate väljade eemaldamiseks ning kontrollimiseks saame kasutada järgnevaid meetodeid:

obj.remove("email");    // Removes "email" field
obj.has("email");       // returns false, because email field was just removed

Väljade kätte saamiseks ja edasiseks manipuleerimiseks saame kasutada järgmisi meetodeid:

obj.get("school");               // Returns field value as JsonElement object
obj.getAsJsonObject("school");   // Returns field value as JsonObject object
obj.getAsJsonArray("grades");    // Returns field value as JsonArray object

// and so on, there are alot of getAs... methods