1. JSON-un Map və List-ə oxunması
Adətən, JSON ilə işləyərkən onun strukturunu əvvəlcədən bilirik və onu Java sinfi şəklində təsvir edə bilirik. Ancaq praktikada hər şey həmişə bu qədər proqnozlaşdırılan olmur: sahələr yarana və itə bilər, iç-içəlik dəyişə bilər. Belə hallarda universal məlumat strukturları — Map, List — və ya JSON ağacları ilə işləmək xeyli rahatdır.
Hər variasiya üçün ayrıca Java modeli yaratmaq — həm vaxt aparır, həm də kövrəkdir. Universal kolleksiyalar və ağaclar sabit sxeməyə bağlanmadan yalnız lazım olan hissələri çevik şəkildə çıxarmağa imkan verir.
JSON obyektinin Map-ə deserializasiyası
JSON nümunəsi:
{
"id": 123,
"name": "Alice",
"email": "alice@example.com",
"active": true
}
Map-ə deserializasiya:
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
public class Main {
public static void main(String[] args) throws Exception {
String json = "{\"id\":123,\"name\":\"Alice\",\"email\":\"alice@example.com\",\"active\":true}";
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> data = mapper.readValue(json, Map.class);
System.out.println(data);
// Çıxış: {id=123, name=Alice, email=alice@example.com, active=true}
}
}
Artıq istənilən sahəyə lüğətin elementi kimi müraciət edə bilərsiniz:
System.out.println(data.get("name")); // Alice
Obyektlər massivinin List-ə deserializasiyası
JSON massivi:
[
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" }
]
Deserializasiya:
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.Map;
public class UsersReadExample {
public static void main(String[] args) throws Exception {
String json = "[{\"id\":1,\"name\":\"Alice\"},{\"id\":2,\"name\":\"Bob\"}]";
ObjectMapper mapper = new ObjectMapper();
List<Map<String, Object>> users = mapper.readValue(json, List.class);
for (Map<String, Object> user : users) {
System.out.println(user.get("name"));
}
// Çıxış:
// Alice
// Bob
}
}
Vacib nüans: universal strukturlara oxuyarkən bütün iç-içə obyektlər Map-ə, massivlər isə List-ə çevrilir. Mürəkkəb strukturlar üçün tipləri diqqətlə çevirmək və onları yoxlamaq lazım gələcək:
Object items = data.get("items");
if (items instanceof List) {
List<?> itemList = (List<?>) items;
// ...
}
2. JsonNode: Jackson-da JSON ağacı
Map/List ilə işləmək rahatdır, amma təhlükəsiz deyil: tiplə səhvə yol vermək və ya iç-içəliyi gözdən qaçırmaq mümkündür. Jackson daha güclü bir alət təklif edir — JsonNode klası. Bu, hər düyünü obyekt, massiv, dəyər və ya null olan universal ağacdır.
JsonNode-un əldə edilməsi
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
public class JsonNodeStart {
public static void main(String[] args) throws Exception {
String json = "{\"id\":123,\"name\":\"Alice\",\"tags\":[\"java\",\"json\"]}";
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
// root — JSON ağacının köküdür
}
}
Sahələrə giriş
int id = root.get("id").asInt(); // 123
String name = root.get("name").asText(); // Alice
JsonNode tags = root.get("tags"); // massiv
System.out.println("Ad: " + name);
Massivin üzərinə keçmək
for (JsonNode tag : tags) {
System.out.println(tag.asText());
}
// Çıxış:
// java
// json
İç-içə obyektlər
Mürəkkəb JSON nümunəsi:
{
"user": {
"id": 1,
"profile": {
"nickname": "java_guru",
"age": 25
}
}
}
İç-içə dəyərin çıxarılması:
JsonNode profile = root.get("user").get("profile");
String nickname = profile.get("nickname").asText();
System.out.println(nickname); // java_guru
Təhlükəsiz giriş: get vs path
- get("açar") — əgər açar yoxdursa, null qaytaracaq. null üzərində asText() kimi istənilən çağırış NullPointerException-a səbəb olacaq.
- path("açar") — əgər açar yoxdursa, “boş” düyün qaytarır və asText() "", asInt() isə 0 verəcək.
String phone = root.path("phone").asText(); // "" sahə yoxdursa
Düyünün tipinin yoxlanması
if (root.has("tags") && root.get("tags").isArray()) {
for (JsonNode tag : root.get("tags")) {
// ...
}
}
JsonNode-un modifikasiyası
JsonNode — dəyişməzdir. Ağacı yaratmaq/dəyişdirmək üçün ObjectNode/ArrayNode istifadə edin.
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
ObjectMapper mapper = new ObjectMapper();
// Yeni obyektin yaradılması
ObjectNode obj = mapper.createObjectNode();
obj.put("id", 10);
obj.put("name", "Bob");
// Massivin əlavə edilməsi
ArrayNode arr = mapper.createArrayNode();
arr.add("Java").add("JSON");
obj.set("tags", arr);
System.out.println(obj.toPrettyString());
/*
{
"id" : 10,
"name" : "Bob",
"tags" : [ "Java", "JSON" ]
}
*/
3. Gson ilə iş: JsonElement, JsonObject, JsonArray
Jackson yeganə seçim deyil. Gson da dinamik JSON üçün rahat API təqdim edir: JsonElement, JsonObject, JsonArray.
JsonElement-ə pars etmək
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
String json = "{\"id\":123,\"name\":\"Alice\",\"tags\":[\"java\",\"json\"]}";
JsonElement root = JsonParser.parseString(json);
Sahələrə giriş
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
JsonObject obj = root.getAsJsonObject();
int id = obj.get("id").getAsInt();
String name = obj.get("name").getAsString();
JsonArray tags = obj.getAsJsonArray("tags");
for (JsonElement tag : tags) {
System.out.println(tag.getAsString());
}
İç-içəlik və təhlükəsizlik
if (obj.has("email")) {
String email = obj.get("email").getAsString();
}
Massivlərlə iş
String arrJson = "[{\"id\":1},{\"id\":2}]";
JsonArray arr = JsonParser.parseString(arrJson).getAsJsonArray();
for (JsonElement el : arr) {
JsonObject item = el.getAsJsonObject();
System.out.println(item.get("id").getAsInt());
}
Modifikasiya
Gson-da obyektlər dəyişəndir — sahələr əlavə edib silmək olar:
import com.google.gson.JsonObject;
JsonObject newObj = new JsonObject();
newObj.addProperty("id", 42);
newObj.add("tags", tags);
System.out.println(newObj.toString());
4. Təcrübə: naməlum JSON-dan məlumatların çıxarılması
Tapşırıq: Tutaq ki, strukturu dəyişə bilən JSON konfiqurasiyamız var:
{
"service": "mail",
"enabled": true,
"params": {
"host": "smtp.example.com",
"port": 587
}
}
Jackson vasitəsilə host və port-u çıxarmaq:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
JsonNode params = root.path("params");
String host = params.path("host").asText();
int port = params.path("port").asInt();
System.out.println(host + ":" + port); // smtp.example.com:587
Eynisi Gson ilə:
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
JsonObject rootObj = JsonParser.parseString(json).getAsJsonObject();
JsonObject params = rootObj.getAsJsonObject("params");
String host = params.get("host").getAsString();
int port = params.get("port").getAsInt();
System.out.println(host + ":" + port);
5. Tipik səhvlər və nüanslar
Səhv №1: Yanlış tip çevrilməsi. Əgər siz sətir gözləyirsinizsə, amma sahədə rəqəm və ya null varsa, asText() və ya getAsString() çağırışı gözlənilməz nəticə və ya istisna verə bilər. Məsələn, sahə olmadıqda root.get("foo").asText() NullPointerException-a gətirəcək.
Səhv №2: null yoxlamasının olmaması. Xüsusilə iç-içə müraciətlərdə: root.get("params").get("host"). Əgər params yoxdursa — NPE olacaq. Jackson-da path() istifadə edin, Gson-da — mövcudluğu has ilə, tipi isə isJsonObject()/isJsonArray() ilə yoxlayın.
Səhv №3: düyün tiplərinin qarışdırılması. Əgər sahə massivdirsə, siz isə ona obyekt kimi müraciət edirsinizsə — səhv alacaqsınız. Tipləri yoxlayın: Jackson — isArray()/isObject(), Gson — isJsonArray()/isJsonObject().
Səhv №4: Map/List ilə işləyərkən tiplər barədə məlumatın itirilməsi. Map<String, Object>-ə deserializasiya zamanı iç-içə strukturlar Map/List zəncirinə çevrilir, bu da naviqasiyanı çətinləşdirir və çoxlu tip çevirmələrinə və instanceof yoxlamalarına gətirib çıxarır.
Səhv №5: ağacın (qeyri-)dəyişənliyini başa düşməmək. Jackson-da JsonNode dəyişməzdir, dəyişikliklər ObjectNode və ArrayNode vasitəsilə edilməlidir. Gson-da obyektlər dəyişəndir; unutmayın ki, düyünün dəyişdirilməsi cari ağacdakı ona olan bütün istinadlara təsir edir.
GO TO FULL VERSION