JSON (JavaScript Object Notation) — це легкий текстовий формат для обміну даними, який є простим для читання та запису як людиною, так і машиною. Формат базується на структурі об’єктів JavaScript і широко використовується для передачі даних між клієнтом і сервером в веб-додатках. Його простота робить його одним із найбільш популярних форматів для зберігання та передачі структурованої інформації.
В процесі написання коду часто виникає необхідність оновлення даних, що зберігаються у форматі JSON. Наприклад, оновлення конфігурацій, додавання нових налаштувань, зміна користувацьких даних або збереження результатів роботи програми.
Для роботи з JSON у Java існує декілька популярних бібліотек, серед яких найчастіше використовуються такі: Jackson, Gson, Json.
У цій статті ми розглянемо, як працювати з JSON-файлами у Java, використовуючи ці три бібліотеки. Для цього ми будемо читати JSON-файл, вносити до нього зміни та записувати оновлені дані назад у файл. Ми продемонструємо два підходи: перший — це перетворення JSON у Java-клас, другий — внесення змін безпосередньо у JSON, без перетворення у класи. Незалежно від обраного підходу, всі три бібліотеки повторюватимуть ці основні кроки, але кожна з них використовуватиме свої власні методи.
Перш ніж перейти до практичної частини, розглянемо приклад JSON-файлу, що знаходить у директорії resources/files, який ми будемо використовувати для демонстрації роботи з даними.
{
"products": [
{
"productName": "Wireless Mouse",
"price": 25.99,
"features": [
{
"featureName": "Ergonomic Design",
"isAvailable": true
},
{
"featureName": "Rechargeable Battery",
"isAvailable": false
}
],
"brand": "TechCo",
"inStock": true
},
{
"productName": "Mechanical Keyboard",
"price": 79.99,
"features": [
{
"featureName": "RGB Backlight",
"isAvailable": true
},
{
"featureName": "Programmable Keys",
"isAvailable": true
}
],
"brand": "KeyMaster",
"inStock": false
}
]
}
Клас ProductCatalog
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductCatalog {
private List<Product> products;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Product {
private String productName;
private double price;
private List<Discount> discounts;
private String brand;
private boolean inStock;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Discount {
private String discountDescription;
private String expiryDate;
}
}
}
Gson
Основні методи, які ми використовуємо в роботі з Gson, включають fromJson() для перетворення JSON у Java-об’єкти та toJson() для перетворення Java-об’єктів назад у JSON. У першому прикладі ми покажемо, як використовувати Gson для перетворення JSON-файлу в Java-клас і внесення змін до нього.
public class Main {
public static void main(String[] args) throws IOException {
String filePath = "src/main/resources/files/products.json";
Gson gson = new Gson();
// Читання JSON-файлу і перетворення його у Java-клас ProductCatalog
JsonObject jsonObject = gson.fromJson(new FileReader(filePath), JsonObject.class);
ProductCatalog productCatalog = gson.fromJson(jsonObject, ProductCatalog.class);
// Додавання нової знижки до другого продукту
productCatalog.getProducts().get(1).getDiscounts().add(
new ProductCatalog.Product.Discount("Buy 1 Get 1 Free", "2024-12-15"));
// Запис оновленого Java-об'єкта назад у JSON-файл
try (FileWriter writer = new FileWriter(filePath)) {
gson.toJson(productCatalog, writer);
}
}
}
Однак Gson також дозволяє працювати з JSON безпосередньо, без перетворення в Java-класи. Давайте розглянемо, як це можна зробити.
public class Main {
public static void main(String[] args) throws IOException {
String filePath = "src/main/resources/files/products.json";
// Читання JSON-файлу за допомогою Gson
JsonElement jsonElement = JsonParser.parseReader(new FileReader(filePath));
JsonObject jsonObject = jsonElement.getAsJsonObject();
// Оновлення даних
JsonArray productsArray = jsonObject.getAsJsonArray("products");
JsonObject secondProduct = productsArray.get(1).getAsJsonObject();
JsonArray discountsArray = secondProduct.getAsJsonArray("discounts");
JsonObject newDiscount = new JsonObject();
newDiscount.addProperty("discountDescription", "Buy 1 Get 1 Free");
newDiscount.addProperty("expiryDate", "2024-12-15");
discountsArray.add(newDiscount);
// Запис оновленого JSON назад у файл
try (FileWriter writer = new FileWriter(filePath)) {
writer.write(jsonObject.toString());
}
}
}
Jackson
ObjectMapper це головний клас для роботи з JSON у бібліотеці Kackson, який надає всі необхідні методи для перетворення між JSON та Java-об’єктами та навпаки.
- readTree: Метод, що дозволяє перетворювати JSON у структуру JsonNode, яка надає можливість гнучко працювати з JSON, не перетворюючи його одразу в об’єкт.
- treeToValue: Використовується для перетворення структури JsonNode у Java-об’єкт.
- writeValue: Метод, що дозволяє серіалізувати Java-об’єкт у JSON.
- readValue: Використовується для десеріалізації JSON у Java-об’єкт.
- writeValueAsString: Метод для перетворення Java-об’єкта в JSON-рядок.
Ці методи дозволяють легко працювати з різними форматами даних, зокрема JSON, і зручно перетворювати їх в об’єкти або навпаки.
курси Junior саме для вас.
Приклад використання Jackson для зчитування JSON-файлу, перетворення його у Java-клас і внесення змін:
public class Main {
public static void main(String[] args) throws IOException {
String filePath = "src/main/resources/files/products.json";
ObjectMapper mapper = new ObjectMapper();
// Читання JSON-файлу і перетворення його у Java-клас ProductCatalog
JsonNode rootNode = mapper.readTree(new File(filePath));
ProductCatalog productCatalog = mapper.treeToValue(rootNode, ProductCatalog.class);
// Внесення змін у назві бренду першого продукту
productCatalog.getProducts().get(0).setBrand("New Brand Name");
// Запис оновленого Java-об'єкта назад у JSON-файл
mapper.writeValue(new File(filePath), productCatalog);
}
}
Jackson також надає можливість працювати з JSON-даними напряму, не перетворюючи їх у Java-класи. Розглянемо приклад, де ми працюємо безпосередньо з JSON-структурою, вносимо необхідні зміни і записуємо оновлені дані назад у файл.
public class Main {
public static void main(String[] args) throws IOException {
String filePath = "src/main/resources/files/products.json";
ObjectMapper mapper = new ObjectMapper();
// Читання JSON-файлу і перетворення його у дерево JSON-об'єктів
JsonNode rootNode = mapper.readTree(new File(filePath));
// Отримання масиву продуктів з дерева JSON
ArrayNode productsArray = (ArrayNode) rootNode.get("products");
// Оновлення назви бренду першого продукту
ObjectNode firstProduct = (ObjectNode) productsArray.get(0);
firstProduct.put("brand", "New Brand Name");
// Запис оновленого JSON назад у файл
mapper.writeValue(new File(filePath), rootNode);
}
}
Json
Бібліотека org.json не надає можливостей автоматичної серіалізації та десеріалізації Java-об’єктів, як це роблять Jackson або Gson. Тому при використанні org.json вам доведеться працювати з даними вручну, що робить процес менш зручним, але водночас більш контрольованим. У цьому розділі ми розглянемо два підходи: перетворення JSON-даних у Java-класи та робота з JSON безпосередньо.
При використанні org.json для перетворення JSON у Java-клас, ви повинні вручну зчитувати JSON-дані, створювати відповідні об’єкти і задавати їх значення. Наприклад, якщо ми хочемо змінити значення поля price у нашому JSON, це може виглядати так:
public class Main {
public static void main(String[] args) throws IOException {
String filePath = "src/main/resources/files/products.json";
// Читання JSON-даних з файлу
Path path = Path.of(filePath);
String jsonString = new String(Files.readAllBytes(path));
JSONObject jsonObject = new JSONObject(jsonString);
// Створення об'єкта ProductCatalog
ProductCatalog productCatalog = new ProductCatalog();
// Отримання масиву продуктів з JSON
JSONArray productsArray = jsonObject.getJSONArray("products");
// Цикл для перетворення кожного продукту з JSON у об'єкт Product
for (int i = 0; i < productsArray.length(); i++) {
JSONObject productJson = productsArray.getJSONObject(i);
ProductCatalog.Product product = new ProductCatalog.Product();
product.setProductName(productJson.getString("productName"));
product.setPrice(productJson.getDouble("price"));
product.setBrand(productJson.getString("brand"));
// сетимо інші поля
// Додавання продукту до каталогу
productCatalog.getProducts().add(product);
}
// Внесення змін у поле price для першого продукту
if (!productCatalog.getProducts().isEmpty()) {
productCatalog.getProducts().get(0).setPrice(46.99);
}
// Запис оновленого JSON назад у файл
for (int i = 0; i < productsArray.length(); i++) {
JSONObject productJson = productsArray.getJSONObject(i);
ProductCatalog.Product product = productCatalog.getProducts().get(i);
productJson.put("price", product.getPrice());
}
Files.write(path, jsonObject.toString(4).getBytes());
}
}
Інший підхід — працювати з JSON-даними напряму, не перетворюючи їх у Java-класи. Це може бути корисно, коли вам потрібно внести прості зміни у структуру JSON, наприклад, змінити значення поля без створення додаткових об’єктів:
public class Main {
public static void main(String[] args) throws IOException {
String filePath = "src/main/resources/files/products.json";
// Зчитування JSON-даних з файлу
String jsonString = new String(Files.readAllBytes(Paths.get(filePath)));
JSONObject jsonObject = new JSONObject(jsonString);
// Пряме внесення змін у поле price для першого продукту
jsonObject.getJSONArray("products").getJSONObject(0).put("price", 35.99);
// Запис оновленого JSON назад у файл
Files.write(Paths.get(filePath), jsonObject.toString(4).getBytes());
}
}
Висновок
Ми розглянули два основних підходи до роботи з JSON-даними у Java. Перший підхід полягає у перетворенні JSON у Java-об’єкти, а другий — у роботі з JSON безпосередньо, без використання об’єктів. Кожен із цих підходів має свої переваги та недоліки, і вибір між ними залежить від конкретних вимог вашого проекту.
Перетворення JSON у Java-об’єкти є більш структурованим підходом, який особливо добре підходить для складних проектів зі стабільною структурою даних. Цей підхід дозволяє вам працювати з JSON-даними як з типовими Java-об’єктами, що робить код більш читабельним і зручним для підтримки.
З іншого боку, робота з JSON безпосередньо, без перетворення його у Java-об’єкти, може бути більш гнучкою і швидкою для реалізації, особливо якщо йдеться про прості задачі або динамічні JSON-структури. Це зменшує обсяг коду, оскільки вам не потрібно створювати додаткові класи. Проте, коли структура JSON стає складною або має багато рівнів вкладеності, код може стати менш зрозумілим і важчим для підтримки. Крім того, відсутність типізації у цьому підході може призвести до більшої кількості помилок, які буде важко виявити на етапі компіляції.
Вибір між Jackson, Gson та Json залежить від специфіки вашого проекту. Якщо вам потрібна максимальна гнучкість і можливість роботи зі складними структурами, Jackson буде найкращим вибором. Для швидкої і простої роботи з JSON краще підходить Gson. А для найпростіших задач з мінімальними вимогами до функціональності, Json може бути достатньо. У кожному випадку, вибір інструменту залежить від ваших конкретних потреб та вимог проекту.
🤔 Залишилися запитання про те, як оновити json-файл у Java? - Сміливо задавайте нижче! 💬