ObjectMapper.readValue: примеры (JAVA)
ObjectMapper.readValue(String content, Class valueType): T Описание метода ObjectMapper.readValue и его назначение
Метод ObjectMapper.readValue из библиотеки Jackson служит для десериализации JSON-данных в объекты Java. Вызовы этого метода принимают источник JSON (строка, массив байт, поток, файл и т. п.) и описание целевого типа (Class, TypeReference, JavaType), после чего возвращают объект заданного типа либо выбрасывают исключение при ошибке парсинга или несовместимости типов.
Типичный сценарий применения включает чтение HTTP-ответа, содержимого файла конфигурации или входных данных из потока и преобразование их в POJO, коллекции, массивы или узлы дерева JSON (JsonNode).
Ниже перечислены наиболее распространенные перегрузки метода и их семантика:
- readValue(String content, Class<T> valueType) - десериализация из строки JSON в объект типа T.
- readValue(byte[] src, Class<T> valueType) - десериализация из массива байт.
- readValue(byte[] src, int offset, int len, Class<T> valueType) - десериализация из части массива байт, полезно при буферизации данных.
- readValue(InputStream src, Class<T> valueType) - чтение из потока, применяется при работе с сетевыми или файловыми потоками.
- readValue(Reader src, Class<T> valueType) - чтение из Reader (BufferedReader, StringReader и т. п.).
- readValue(File src, Class<T> valueType) - десериализация из файла.
- readValue(URL src, Class<T> valueType) - загрузка JSON по URL и десериализация.
- readValue(JsonParser p, Class<T> valueType) - десериализация, используя уже созданный JsonParser; используется при низкоуровневой обработке токенов или в парсере потоков.
- readValue(String content, TypeReference<T> valueTypeRef) - вариант для параметризованных типов (например, List<MyType>), где Class не достаточен из‑за type erasure.
- readValue(byte[] src, TypeReference<T> valueTypeRef) - аналогично для байтовых данных с TypeReference.
Возвращаемое значение: объект типа T (или коллекция/массив/JsonNode и т. п.). При ошибках метод бросает исключение: обычно com.fasterxml.jackson.core.JsonParseException для синтаксических ошибок и com.fasterxml.jackson.databind.JsonMappingException (включая подклассы MismatchedInputException, UnrecognizedPropertyException) при несоответствии типов. Так как большинство перегрузок бросают IOException, их следует обрабатывать либо пробрасывать дальше.
Для сложных/параметризованных типов рекомендуется использовать TypeReference<T> или строить JavaType через TypeFactory, т. к. простого Class<T> бывает недостаточно для сохранения информации о параметрах типа.
Короткие примеры различных вариантов использования
Примеры демонстрируют код и ожидаемый результат. В примерах используется зависимость com.fasterxml.jackson.databind.ObjectMapper.
1) Простая десериализация строки в POJO
public class User {
public String name;
public int age;
}
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"Ivan\",\"age\":30}";
User u = mapper.readValue(json, User.class);
System.out.println(u.name + ":" + u.age);
Ivan:30
2) Десериализация в Map
String json = "{\"k\":1,\"v\":true}";
Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>(){});
System.out.println(map);
{k=1, v=true}
3) Список строк с TypeReference
String json = "[\"a\",\"b\"]";
List<String> list = mapper.readValue(json, new TypeReference<List<String>>(){});
System.out.println(list);
[a, b]
4) Чтение из InputStream
byte[] data = "{\"name\":\"Oleg\",\"age\":25}".getBytes(StandardCharsets.UTF_8);
InputStream in = new ByteArrayInputStream(data);
User u2 = mapper.readValue(in, User.class);
System.out.println(u2.name + ", " + u2.age);
Oleg, 25
5) Частичная десериализация из массива байт
byte[] buf = ("garbage" + "{\"name\":\"Nina\",\"age\":27}").getBytes();
// допустим JSON начинается с смещения 7
User u3 = mapper.readValue(buf, 7, buf.length - 7, User.class);
System.out.println(u3.name);
Nina
6) Использование JsonParser
JsonFactory f = mapper.getFactory();
JsonParser p = f.createParser("{\"name\":\"Ann\",\"age\":22}");
User a = mapper.readValue(p, User.class);
System.out.println(a.name + " " + a.age);
Ann 22
Аналоги и близкие API внутри экосистемы Java
В рамках Jackson существуют похожие по назначению методы и классы с особыми преимуществами:
- readTree(String) - возвращает JsonNode, полезно при динамической навигации по структуре JSON без привязки к POJO.
- treeToValue(JsonNode, Class<T>) - преобразование узла дерева в POJO; удобно при частичной обработки дерева.
- ObjectReader.readValues - возвращает MappingIterator<T> для потоковой десериализации нескольких объектов подряд (например, newline-delimited JSON).
- readerForUpdating(T valueToUpdate) в ObjectMapper/ObjectReader - обновление существующего объекта полями из JSON вместо создания нового.
- XmlMapper (Jackson module) - аналогичный API для XML; применяется при работе с XML вместо JSON.
При наличии параллельных требований: динамическая обработка - предпочтительнее readTree/JsonNode, потоковая десериализация больших последовательностей - readerFor / readValues. Для параметризованных типов удобнее ObjectReader с предварительно настроенным JavaType.
Сопоставимые механизмы парсинга JSON в других языках
Краткие альтернативы в популярных языках и их отличия от Java/Jackson:
- JavaScript:
JSON.parse. Простая десериализация в объект/массив, нет встроенной типизации; пример:const obj = JSON.parse('{"a":1}'); console.log(obj.a);1
- Python:
json.loads. Возвращает dict/list. Для строгой валидации типов используются pydantic или dataclasses + dacite.import json obj = json.loads('{"name":"P"}') print(obj['name'])P
- C#:
Newtonsoft.Json.JsonConvert.DeserializeObject<T>илиSystem.Text.Json.JsonSerializer.Deserialize<T>. Поддержка generics и атрибутов для настройки. Пример:var json = "{\"x\":10}"; var obj = JsonConvert.DeserializeObject<Dictionary<string,int>>(json); Console.WriteLine(obj["x"]);10
- Go:
json.Unmarshal. Требует экспортируемых полей (с заглавной буквы) и тегов struct для маппинга. Пример:type User struct {Name string `json:"name"`} var u User json.Unmarshal([]byte(`{"name":"G"}`), &u) fmt.Println(u.Name)G
- PHP:
json_decode. Возвращает ассоциативный массив или объект; для строгих типов используются кастомные мапперы или Symfony Serializer.$o = json_decode('{"n":"x"}', true); print_r($o['n']);x
- Kotlin: может использовать Jackson (тот же API) или kotlinx.serialization с собственными аннотациями; для data class десериализация обычно проще за счет синтаксиса языка.
- Lua: библиотеки типа cjson с функцией
decode, простая динамическая структура. - SQL: в СУБД (PostgreSQL) имеются функции для разбора JSON, например
jsonb_to_recordи операторы доступа, но это не десериализация в объекты JVM.
Отличия от Java/Jackson: статическая типизация Java требует описания целевого типа, что улучшает безопасность, но добавляет сложность при параметризованных типах. В языках с динамической типизацией (JS, Python, PHP) десериализация проще, но проверки типов требуется выполнять отдельно.
Типичные ошибки при использовании и примеры
Ниже перечислены распространённые проблемы с примерами и типичным выводом исключения.
1) Синтаксическая ошибка JSON
String json = "{name: 'Bad'}"; // кавычки не по стандарту
mapper.readValue(json, Object.class);
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'name' (а далее стек)
2) Неизвестное свойство в JSON при строгой конфигурации
public class A { public String known; }
String json = "{\"known\":\"v\",\"x\":1}";
mapper.readValue(json, A.class);
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "x" (а далее стек)
Решение: отключение правила mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) или добавление @JsonIgnoreProperties(ignoreUnknown = true).
3) Несоответствие ожидаемого типа (MismatchedInputException)
String json = "{\"a\":1}"; // объект
List<Integer> list = mapper.readValue(json, new TypeReference<List<Integer>>(){});
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token
4) Отсутствие конструктора без аргументов или неподходящие аннотации
public class NoDefault { private final String x; public NoDefault(String x) { this.x = x; }}
mapper.readValue("{\"x\":\"v\"}", NoDefault.class);
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `NoDefault` (no Creators, like default constructor)
Решение: добавить публичный конструктор без аргументов, использовать @JsonCreator и @JsonProperty или модуль для record/constructor-инъекции.
5) Потоковые проблемы и частичная буферизация
byte[] buf = new byte[1024];
int read = in.read(buf);
mapper.readValue(buf, 0, read, MyType.class);
Возможны ошибки при указании неверного смещения/длины или при неполном JSON: JsonParseException/EOFException
Изменения в поведении и новых возможностях в последних релизах
В последних версиях Jackson происходило постепенное расширение возможностей десериализации: добавлена и улучшена поддержка Java records, расширены возможности для sealed классов и улучшена работа с параметризованными типами через JavaType и TypeFactory. Появились улучшения в десериализации дат и времени, а также опции для более гибкой конфигурации десериализаторов.
Также в новых версиях усилены проверки безопасности парсинга (например, контроль разрешённых типов при полиморфной десериализации) и добавлены дополнительные опции конфигурации для ObjectReader/ObjectWriter. При обновлении рекомендуется сверять release notes конкретной версии библиотеки, так как детали поведения и рекомендованные подходы могли измениться.
Расширенные и редкие сценарии применения
Ниже приведены более сложные примеры с пояснениями.
1) Потоковая десериализация множества объектов (NDJSON - newline-delimited JSON)
String ndjson = "{\"id\":1}\n{\"id\":2}\n";
MappingIterator<Item> it = mapper.readerFor(Item.class).readValues(ndjson);
while (it.hasNext()) {
Item itObj = it.next();
System.out.println(itObj.id);
}
1 2
2) Обновление существующего объекта (merge)
User target = new User();
target.name = "Old";
String json = "{\"age\":40}";
mapper.readerForUpdating(target).readValue(json);
System.out.println(target.name + ", " + target.age);
Old, 40
Пояснение: readerForUpdating не перезаписывает поля, отсутствующие в JSON.
3) Десериализация с использованием JavaType для сложных generic-типов
JavaType type = mapper.getTypeFactory().constructCollectionType(List.class,
mapper.getTypeFactory().constructParametricType(Result.class, User.class));
List<Result<User>> res = mapper.readValue(json, type);
Список объектов Result<User> (в зависимости от входа)
4) Полиморфная десериализация с использованием @JsonTypeInfo
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({@JsonSubTypes.Type(value = A.class, name = "a"), @JsonSubTypes.Type(value = B.class, name = "b")})
public abstract class Base {}
String json = "{\"type\":\"a\",\"field\":1}";
Base b = mapper.readValue(json, Base.class);
System.out.println(b.getClass().getSimpleName());
A
5) Использование собственного десериализатора для нестандартного формата
public class EpochDateDeserializer extends StdDeserializer<Date> {
public EpochDateDeserializer() { super(Date.class); }
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
long epoch = p.getLongValue();
return new Date(epoch * 1000L);
}
}
SimpleModule mod = new SimpleModule();
mod.addDeserializer(Date.class, new EpochDateDeserializer());
mapper.registerModule(mod);
Date d = mapper.readValue("1620000000", Date.class);
System.out.println(d);
Дата, соответствующая epoch в секундах
6) Десериализация Java record
public record Point(int x, int y) {}
String json = "{\"x\":10,\"y\":20}";
Point p = mapper.readValue(json, Point.class);
System.out.println(p);
Point[x=10, y=20]
7) Чтение при частичной буферизации (например, при чтении по сети с предварительным заголовком)
byte[] buffer = new byte[4096];
int header = in.read(buffer, 0, 128); // прочитан заголовок
int jsonLen = in.read(buffer, 128, 512); // прочитана JSON часть
MyType obj = mapper.readValue(buffer, 128, jsonLen, MyType.class);
MyType объект (при корректном JSON)
8) Инъекция зависимостей и использование InjectableValues
mapper.setInjectableValues(new InjectableValues.Std().addValue("now", Instant.now()));
public class C { @JacksonInject("now") public Instant now; }
C c = mapper.readValue("{}", C.class);
System.out.println(c.now);
Текущее время, переданное через InjectableValues
Эти примеры демонстрируют гибкость ObjectMapper.readValue: метод работает в простых и сложных сценариях, от потоковой десериализации до полиморфизма и пользовательских десериализаторов.
джава ObjectMapper.readValue function comments
- джава ObjectMapper.readValue - аргументы и возвращаемое значение
- Функция java ObjectMapper.readValue - описание
- ObjectMapper.readValue - примеры
- ObjectMapper.readValue - похожие методы на java
- ObjectMapper.readValue на javascript, c#, python, php
- ObjectMapper.readValue изменения java
- Примеры ObjectMapper.readValue на джава