Gson.fromJson: примеры (JAVA)
Gson.fromJson(String json, Class classOfT): T Описание и сигнатуры
Метод Gson.fromJson из библиотеки Gson выполняет десериализацию JSON-строки или потока в объект Java. Применяется при преобразовании JSON в примитивы, POJO, коллекции и сложные параметризованные типы. Вызовы основываются на экземпляре com.google.gson.Gson, у которого поведение можно настраивать через GsonBuilder.
Основные перегрузки:
public <T> T fromJson(String json, Class<T> classOfT)- десериализация из строки в класс без параметризации. Возвращает объект типаTилиnull, если JSON равен"null"или входnull.public <T> T fromJson(Reader json, Class<T> classOfT)- как выше, но читает изReader(поддержка потоковой обработки больших JSON).public <T> T fromJson(String json, Type typeOfT)- позволяет десериализовать в параметризованные типы (например,List<MyClass>) с использованиемjava.lang.reflect.Type(обычно создаётся черезTypeToken).public <T> T fromJson(Reader json, Type typeOfT)- аналогично, но сReader.public <T> T fromJson(JsonElement json, Class<T> classOfT)- десериализация из уже распарсенного дереваJsonElement.- Другие варианты принимают
JsonReaderдля точечного управления потоковым чтением.
Параметры и возвращаемые значения
- json (String/Reader/JsonElement/JsonReader) - исходный JSON-источник. При
nullвозвращаетnullдля большинства перегрузок. - classOfT (Class<T>) - сырой класс для простых типов. Не поддерживает сохранение информации о параметрах дженериков (например, не различит List<String> и List<Integer>).
- typeOfT (Type) - отражает полную информацию о типе, включая параметризацию. Обычно создаётся через
new TypeToken<...>(){}.getType(). - Возвращаемое значение - объект типа
T, может бытьnull. Время выполнения десериализации зависит от структуры JSON, пользовательских адаптеров и размера данных.
Особенности: возвращаемые объекты создаются с помощью рефлексии, при отсутствии публичного конструктора могут использоваться InstanceCreator или специальные адаптеры. Поведение при несоответствии типов контролируется через пользовательские десериализаторы и настройки GsonBuilder (например, serializeNulls, политики именования, обработка дат).
Короткие примеры
1) Простая десериализация в POJO
class User { String name; int age; }
Gson g = new Gson();
String json = "{\"name\":\"Иван\",\"age\":30}";
User u = g.fromJson(json, User.class);
System.out.println(u.name + ", " + u.age);
Иван, 30
2) Десериализация списка с использованием TypeToken
Type listType = new com.google.gson.reflect.TypeToken
[a, b]
3) Map из строки
Type mapType = new com.google.gson.reflect.TypeToken
1
4) Чтение из Reader (файл или InputStream)
try (java.io.Reader r = new java.io.StringReader("{\"Name\":\"A\"}")) {
Gson g = new Gson();
MyClass m = g.fromJson(r, MyClass.class);
System.out.println(m.Name);
}
A
5) Десериализация JsonElement
Gson g = new Gson();
com.google.gson.JsonElement el = com.google.gson.JsonParser.parseString("{\"v\":10}");
Data d = g.fromJson(el, Data.class);
System.out.println(d.v);
10
Похожие библиотеки на Java
- Jackson (com.fasterxml.jackson) - очень производительная и функциональная библиотека. Лучше подходит при сложной сериализации, аннотациях для контроля и потоковой обработке (TreeModel, Streaming API). Предпочтительна при требованиях к скорости и гибкой конфигурации.
- JSON-B (javax.json.bind) - стандартная спецификация для Java, интегрируется с CDI и другими стандартами. Удобна при переносимости и использовании внутри Jakarta EE.
- Moshi - компактная библиотека от Square, удобна для Android, имеет хорошую поддержку Kotlin и адаптеров.
- org.json / JSON.simple - лёгкие варианты для простых случаев, не дают автоматического маппинга на POJO без дополнительного кода.
Выбор зависит от нужд: для простоты и минимальных зависимостей часто выбирают Gson; для производительности и расширяемости - Jackson; для стандартов и интеграции со стеком Jakarta - JSON-B.
Аналоги в других языках и отличия
PHP
// json_decode в PHP
$json = '{"name":"Иван","age":30}';
$obj = json_decode($json);
echo $obj->name . ", " . $obj->age;
Иван, 30
Отличие: встроенная функция, возвращает stdClass или ассоциативный массив; без типов Java.
JavaScript
const json = '{"a":1}';
const obj = JSON.parse(json);
console.log(obj.a);
1
Отличие: нативная функция, динамическая типизация, отсутствуют POJO-классы.
Python
import json
obj = json.loads('{"x":10}')
print(obj['x'])
10
Отличие: стандартная библиотека возвращает dict/list; для строгой типизации используются pydantic или dataclasses + dacite.
C#
// Newtonsoft.Json
using Newtonsoft.Json;
var s = "{\"n\":\"A\"}";
var o = JsonConvert.DeserializeObject<MyCls>(s);
Console.WriteLine(o.n);
A
Отличие: сильная статическая типизация, богатые возможности настройки через атрибуты; имеются две популярные реализации: Newtonsoft и System.Text.Json.
Go
// encoding/json
package main
import (
"encoding/json"
"fmt"
)
func main(){
var m map[string]int
json.Unmarshal([]byte("{\"a\":1}"), &m)
fmt.Println(m["a"])
}
1
Отличие: требуется передавать указатель на структуру; строгая проверка типов при маршалинге.
Kotlin
// Gson в Kotlin
val g = Gson()
val u = g.fromJson("{\"name\":\"A\"}", User::class.java)
println(u.name)
A
Отличие: те же библиотеки, но есть kotlin-specific решения (kotlinx.serialization) с более тесной интеграцией и безопасностью типов.
Lua
local json = require 'cjson'
local t = json.decode('{"k":5}')
print(t.k)
5
Отличие: лёгкие парсеры, динамическая типизация.
SQL (пример для PostgreSQL)
-- Преобразование JSON в строки/поля
SELECT (data->>'name') AS name FROM (SELECT '{"name":"Ivan"}'::json AS data) s;
name Ivan
Отличие: SQL выполняет извлечение значений из JSON в контексте запросов, не маппит на объекты JVM прямо.
Типичные ошибки и их симптомы
- JsonSyntaxException - синтаксическая ошибка в JSON. Пример: непарные кавычки или лишняя запятая.
- JsonParseException - общая ошибка парсинга, часто от кастомного десериализатора.
- ClassCastException - попытка привести результирующий объект к несовместимому типу; часто при неверном TypeToken или использовании Class вместо Type для дженериков.
- NullPointerException - доступ к полю у
null, если JSON не содержит поле и код не проверяет на null. - MalformedJsonException - поток содержит неполный или повреждённый JSON при использовании
Readerили стриминга.
Примеры:
Gson g = new Gson();
String bad = "{\"x\":1,"; // лишняя запятая
g.fromJson(bad, Map.class);
com.google.gson.stream.MalformedJsonException: Unterminated object at line 1 column 8
Gson g = new Gson();
String json = "[1,2]";
// Неверно: приведение к Integer
Integer x = g.fromJson(json, Integer.class);
java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.Integer
Рекомендации устранения: валидировать JSON, использовать правильные сигнатуры с TypeToken для дженериков, добавлять обработку null и настраивать десериализаторы для специальных типов.
Изменения в последних версиях
Gson в целом сохраняет обратную совместимость. В обновлениях последних версий (ряд 2.8.x и далее) были исправлены баги, улучшена обработка некоторых крайних случаев и добавлена поддержка новых платформ. Также происходили небольшие улучшения в производительности и исправления при работе с потоковым API.
Важные моменты:
- Частые правки касаются устойчивости к некорректному JSON и корректности обработки числовых типов.
- Добавление возможностей по удобному созданию адаптеров и более тщательной обработке null-значений через
GsonBuilder.
Прямых кардинальных изменений API метода fromJson не наблюдается: сигнатуры сохраняются стабильными, основная эволюция - в поведении парсера и исправления багов.
Расширенные и редкие сценарии
1) Полиморфная десериализация через RuntimeTypeAdapterFactory
// Требует реализации фабрики; пример концепта
abstract class Animal { String name; }
class Cat extends Animal { int lives; }
class Dog extends Animal { String breed; }
RuntimeTypeAdapterFactory<Animal> rta = RuntimeTypeAdapterFactory.of(Animal.class, "type")
.registerSubtype(Cat.class, "cat")
.registerSubtype(Dog.class, "dog");
Gson g = new GsonBuilder().registerTypeAdapterFactory(rta).create();
String js = "{\"type\":\"cat\",\"name\":\"Мур\",\"lives\":9}";
Animal a = g.fromJson(js, Animal.class);
System.out.println(a.getClass().getSimpleName());
Cat
2) Потоковая обработка большого массива через Reader для экономии памяти
Gson g = new Gson();
try (java.io.Reader r = new java.io.FileReader("big.json")) {
java.io.BufferedReader br = new java.io.BufferedReader(r);
Type itemType = new com.google.gson.reflect.TypeToken<Item>(){}.getType();
com.google.gson.stream.JsonReader jr = new com.google.gson.stream.JsonReader(br);
jr.beginArray();
while (jr.hasNext()) {
Item it = g.fromJson(jr, Item.class); // десериализация по одному элементу
// обработка it
}
jr.endArray();
}
(без вывода - пример потоковой обработки)
3) Кастомный десериализатор для нестандартного формата даты
class DateDeserializer implements com.google.gson.JsonDeserializer<java.util.Date> {
public Date deserialize(com.google.gson.JsonElement json, java.lang.reflect.Type typeOfT,
com.google.gson.JsonDeserializationContext context) {
String s = json.getAsString();
// собственный парсер, например Unix timestamp в строке
long ts = Long.parseLong(s);
return new java.util.Date(ts * 1000L);
}
}
Gson g = new GsonBuilder().registerTypeAdapter(java.util.Date.class, new DateDeserializer()).create();
String js = "{\"d\":\"1633046400\"}";
class C{ Date d; }
C c = g.fromJson(js, C.class);
System.out.println(c.d);
Fri Oct 01 00:00:00 UTC 2021
4) Десериализация immutable класса через InstanceCreator
class Point { final int x; final int y;
Point(int x, int y){ this.x = x; this.y = y; }
}
class PointCreator implements com.google.gson.InstanceCreator<Point> {
public Point createInstance(java.lang.reflect.Type type) {
return new Point(0,0); // потом поля заменяются через Reflection или адаптер
}
}
Gson g = new GsonBuilder().registerTypeAdapter(Point.class, new PointCreator()).create();
Point p = g.fromJson("{\"x\":5,\"y\":6}", Point.class);
System.out.println(p.x + "," + p.y);
5,6
5) Десериализация с полями, имеющими нестандартные имена (FieldNamingPolicy)
Gson g = new GsonBuilder().setFieldNamingPolicy(com.google.gson.FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
String js = "{\"first_name\":\"A\"}";
class P{ String firstName; }
P p = g.fromJson(js, P.class);
System.out.println(p.firstName);
A
6) Использование JsonDeserializer для частичной обработки полей
class WrapperDeserializer implements com.google.gson.JsonDeserializer<Wrapper> {
public Wrapper deserialize(com.google.gson.JsonElement je, java.lang.reflect.Type t,
com.google.gson.JsonDeserializationContext c) {
com.google.gson.JsonObject obj = je.getAsJsonObject();
// парсить только нужные поля вручную
String s = obj.has("s") ? obj.get("s").getAsString() : "";
return new Wrapper(s);
}
}
Gson g = new GsonBuilder().registerTypeAdapter(Wrapper.class, new WrapperDeserializer()).create();
Wrapper w = g.fromJson("{\"s\":\"ok\",\"x\":1}", Wrapper.class);
System.out.println(w);
Wrapper@... (в зависимости от реализации toString)
7) Десериализация чисел в BigDecimal для точности
Gson g = new GsonBuilder().setObjectToNumberStrategy(com.google.gson.ToNumberPolicy.BIG_DECIMAL).create();
String js = "{\"v\":0.1}";
com.google.gson.JsonObject o = g.fromJson(js, com.google.gson.JsonObject.class);
System.out.println(o.get("v").getAsBigDecimal());
0.1
8) Обработка отсутствующих полей с установкой значений по умолчанию в десериализаторе
class WithDefaultsDeserializer implements com.google.gson.JsonDeserializer<Cfg> {
public Cfg deserialize(com.google.gson.JsonElement je, java.lang.reflect.Type t,
com.google.gson.JsonDeserializationContext c) {
com.google.gson.JsonObject o = je.getAsJsonObject();
int limit = o.has("limit") ? o.get("limit").getAsInt() : 100; // дефолт
return new Cfg(limit);
}
}
Gson g = new GsonBuilder().registerTypeAdapter(Cfg.class, new WithDefaultsDeserializer()).create();
Cfg c = g.fromJson("{}", Cfg.class);
System.out.println(c.limit);
100
В каждом случае ключевой момент - выбор правильной сигнатуры fromJson и, при необходимости, регистрация адаптеров или фабрик в GsonBuilder. Это даёт контроль над поведением десериализации и позволяет удовлетворить нетипичные требования.