Gson.fromJson: примеры (JAVA)

Десериализация JSON в Java с помощью Gson.fromJson
Раздел: Работа с JSON (Jackson, Gson, JSON-P)
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

Пример java
// Требует реализации фабрики; пример концепта
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 для экономии памяти

Пример java
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) Кастомный десериализатор для нестандартного формата даты

Пример java
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

Пример java
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)

Пример java
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 для частичной обработки полей

Пример java
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 для точности

Пример java
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) Обработка отсутствующих полей с установкой значений по умолчанию в десериализаторе

Пример java
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. Это даёт контроль над поведением десериализации и позволяет удовлетворить нетипичные требования.

джава Gson.fromJson function comments

En
Gson.fromJson Deserializes the specified Json into an object of the specified class