ObjectMapper.writeValueAsString: примеры (JAVA)
ObjectMapper.writeValueAsString(Object value): StringОписание метода и его контракт
В Jackson класс com.fasterxml.jackson.databind.ObjectMapper предоставляет метод writeValueAsString, который выполняет сериализацию объекта Java в строку в формате JSON.
Подпись метода:
public String writeValueAsString(Object value) throws com.fasterxml.jackson.core.JsonProcessingException
Параметры и поведение:
- value - объект для сериализации. Может быть
null, примитивом, массивом, коллекцией, отображением (Map), POJO, Java Date/Time и т. п. Для некоторых типов требуется подключение модулей (например,JavaTimeModuleдля java.time). - Возвращаемое значение - строка JSON (
String), содержащая сериализованное представление объекта. Дляnullвозвращается строка"null"(в формате JSON), а неnullJava-ссылка. - Исключения - метод бросает
JsonProcessingException(или подклассы), если сериализация невозможна (например, нет сериализатора для типа, рекурсивная ссылка без обработки, ошибки преобразования).
Контекст использования:
- Преобразование объектов в JSON для HTTP-ответов, логирования, кеширования, хранения конфигураций и передачи через сообщения.
- Быстрая сериализация при отладке, когда требуется получить JSON в виде строки.
Важные настройки, влияющие на результат:
- SerializationFeature (например,
INDENT_OUTPUTдля форматирования,WRITE_DATES_AS_TIMESTAMPSдля дат). - PropertyNamingStrategy для изменения имён полей в JSON (пример: snake_case).
- Модули - регистрация модулей (например,
JavaTimeModule,ParameterNamesModule, кастомные модули). - MixIn-аннотации и custom serializers для изменения сериализации без изменения исходного класса.
Особенности потокобезопасности: экземпляр ObjectMapper рекомендуется настраивать один раз и переиспользовать. После завершения конфигурации он безопасен для доступа из разных потоков.
Короткие примеры использования
1) Простейшая сериализация POJO:
import com.fasterxml.jackson.databind.ObjectMapper;
public class User { public String name; public int age; }
ObjectMapper om = new ObjectMapper();
User u = new User(); u.name = "Ivan"; u.age = 30;
String json = om.writeValueAsString(u);
System.out.println(json);
{"name":"Ivan","age":30}
2) Сериализация коллекции:
List<String> list = Arrays.asList("a","b","c");
String json = new ObjectMapper().writeValueAsString(list);
System.out.println(json);
["a","b","c"]
3) Pretty print (красивый вывод):
ObjectMapper om = new ObjectMapper();
om.enable(com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT);
Map<String,Object> map = new HashMap<>();
map.put("ok", true); map.put("count", 5);
String json = om.writeValueAsString(map);
System.out.println(json);
{
"ok" : true,
"count" : 5
}
4) Дата и время (без модуля):
Map<String,Object> m = Collections.singletonMap("date", java.time.LocalDate.now());
String j = new ObjectMapper().writeValueAsString(m);
System.out.println(j);
{"date":{...}} // без JavaTimeModule результат может быть неинтуитивен или приведёт к ошибке сериализации, зависит от версии Jackson
5) Пользовательский сериализатор (микропример):
public class BoolAsIntSerializer extends com.fasterxml.jackson.databind.JsonSerializer<Boolean> {
@Override public void serialize(Boolean value, com.fasterxml.jackson.core.JsonGenerator gen,
com.fasterxml.jackson.databind.SerializerProvider serializers) throws java.io.IOException {
gen.writeNumber(value ? 1 : 0);
}
}
ObjectMapper om = new ObjectMapper();
SimpleModule mod = new SimpleModule();
mod.addSerializer(Boolean.class, new BoolAsIntSerializer());
om.registerModule(mod);
String s = om.writeValueAsString(Collections.singletonMap("flag", true));
System.out.println(s);
{"flag":1}Похожие подходы в Java и их отличия
1) Gson (com.google.gson.Gson): простая и компактная альтернатива. Проще в настройке, но меньше возможностей по расширенной кастомизации и интеграции с модулями Jackson. Пример: new Gson().toJson(obj). Подходит для простых случаев.
2) JSON-B (Jakarta JSON Binding, Jsonb): стандартная спецификация для привязки Java↔JSON. Менее популярна, чем Jackson, но хороша при желании следовать стандартам Jakarta EE.
3) org.json (JSONObject#toString): минималистичный подход, полезен для простых задач или когда нужен быстрый парсер/строитель JSON без сложной сериализации POJO.
4) Внутренние методы ObjectMapper: writeValue(File, obj), writeValue(OutputStream, obj), writeValueAsBytes(obj). Они отличаются целью вывода (файл, поток, байты) и могут быть предпочтительнее, когда требуются потоки или бинарный буфер.
Выбор основывается на требованиях: сложная сериализация, аннотации и интеграция с экосистемой - Jackson; компактность и простота - Gson; совместимость со стандартом Jakarta - JSON-B.
Как это делается в других языках
PHP - json_encode:
$arr = ['name' => 'Ivan', 'age' => 30];
echo json_encode($arr);
{"name":"Ivan","age":30}
JavaScript - JSON.stringify:
const obj = { name: 'Ivan', age: 30 };
console.log(JSON.stringify(obj));
{"name":"Ivan","age":30}
Python - json.dumps:
import json
print(json.dumps({'name':'Ivan','age':30}))
{"name": "Ivan", "age": 30}
C# - Newtonsoft.Json и System.Text.Json:
// Newtonsoft
var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
// System.Text.Json
var json2 = System.Text.Json.JsonSerializer.Serialize(obj);
{"name":"Ivan","age":30}
Go - encoding/json:
b, _ := json.Marshal(map[string]interface{}{"name":"Ivan","age":30})
fmt.Println(string(b))
{"name":"Ivan","age":30}
Kotlin - можно использовать Jackson или kotlinx.serialization:
// Jackson
val json = jacksonObjectMapper().writeValueAsString(data)
// kotlinx.serialization
val json2 = Json.encodeToString(data)
{"name":"Ivan","age":30}
Lua - cjson:
local cjson = require 'cjson'
print(cjson.encode({name='Ivan', age=30}))
{"name":"Ivan","age":30}
SQL (пример PostgreSQL) - функции для JSON-формирования:
SELECT row_to_json(t) FROM (SELECT 'Ivan' AS name, 30 AS age) t;
{"name":"Ivan","age":30}
Отличия от Java/Jackson: в большинстве языков сериализация возвращает строку напрямую и имеет более простые механизмы расширения. Jackson выделяется богатой системой модулей, аннотациями и возможностью тонкой настройки сериализации и десериализации.
Типичные ошибки при использовании и примеры
1) Отсутствие сериализатора для типа (например, для некоторых сторонних классов):
class NoSerializerHolder { Object value; }
ObjectMapper om = new ObjectMapper();
NoSerializerHolder h = new NoSerializerHolder();
h.value = new java.sql.Connection() { /* интерфейс, не сериализуемый */ };
om.writeValueAsString(h);
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.sql.Connection ...
Решение: реализовать/зарегистрировать кастомный сериализатор или исключить поле с помощью аннотаций/микса.
2) Бесконечная рекурсия при сериализации взаимно ссылающихся объектов:
class A { public B b; }
class B { public A a; }
A a = new A(); B b = new B(); a.b = b; b.a = a;
new ObjectMapper().writeValueAsString(a);
com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError ...) or similar
Варианты решения: использовать @JsonIdentityInfo, @JsonManagedReference/@JsonBackReference, или отключить сериализацию некоторых полей.
3) Неправильная сериализация java.time без модуля:
Map<String,Object> m = Map.of("dt", java.time.LocalDateTime.now());
new ObjectMapper().writeValueAsString(m);
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type not supported by default
Решение: зарегистрировать JavaTimeModule и настроить формат даты.
4) Неправильная конфигурация default typing (полиморфная сериализация):
ObjectMapper om = new ObjectMapper();
om.activateDefaultTyping(om.getPolymorphicTypeValidator(), com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping.NON_FINAL);
String s = om.writeValueAsString(List.of(1,2,3));
JSON содержит служебную информацию о типах, что может быть нежелательно и создавать проблемы с безопасностью
Решение: избегать включения default typing без проверки PolymorphicTypeValidator и понимать последствия для безопасности.
Изменения и важные приметы в последних релизах
- Поддержка Java-records и улучшенная интеграция с современными конструкциями Java появилась в релизах Jackson 2.12 и выше - это упростило сериализацию/десериализацию record-классов.
- Изменён подход к безопасной полиморфной десериализации: старые методы вроде
enableDefaultTypingсчитаются небезопасными; рекомендуется использоватьPolymorphicTypeValidatorпри необходимости полиморфной десериализации. - Работа с Java 8+ датами улучшена: распространённый паттерн - регистрация
JavaTimeModuleи настройкаSerializationFeature.WRITE_DATES_AS_TIMESTAMPS. - Постепенные оптимизации производительности и API-фиксы; сигнатура
writeValueAsStringустойчива и изменений в ней нет, но поведение может зависеть от более новых модулей и настроек по умолчанию.
Расширенные и нетипичные сценарии
1) Сериализация LocalDateTime с форматом ISO:
ObjectMapper om = new ObjectMapper();
com.fasterxml.jackson.datatype.jsr310.JavaTimeModule jtm = new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule();
jtm.addSerializer(java.time.LocalDateTime.class,
new com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME));
om.registerModule(jtm);
om.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
String s = om.writeValueAsString(java.time.LocalDateTime.of(2023,1,2,15,30));
System.out.println(s);
"2023-01-02T15:30:00"
2) Фильтрация полей с помощью SimpleBeanPropertyFilter:
public class User { public String name; public String secret; }
ObjectMapper om = new ObjectMapper();
FilterProvider filters = new com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider()
.addFilter("myFilter", com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter.serializeAllExcept("secret"));
om.setFilterProvider(filters);
// MixIn для привязки фильтра к классу
om.addMixIn(User.class, UserFilterMixIn.class);
User u = new User(); u.name = "Ivan"; u.secret = "x";
String out = om.writeValueAsString(u);
System.out.println(out);
// MixIn
@interface UserFilterMixIn { }
@com.fasterxml.jackson.annotation.JsonFilter("myFilter")
interface UserFilterMixIn { }
{"name":"Ivan"}
3) Обход циклических ссылок с @JsonIdentityInfo:
@com.fasterxml.jackson.annotation.JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="id")
class Node { public int id; public Node parent; }
Node a = new Node(); a.id = 1;
Node b = new Node(); b.id = 2; b.parent = a; a.parent = b;
String s = new ObjectMapper().writeValueAsString(a);
System.out.println(s);
{"id":1,"parent":{"id":2,"parent":1}}
4) Сериализация с разными View (JsonView):
class Data {
@com.fasterxml.jackson.annotation.JsonView(Views.Public.class)
public String name;
@com.fasterxml.jackson.annotation.JsonView(Views.Internal.class)
public String secret;
}
ObjectMapper om = new ObjectMapper();
String pub = om.writerWithView(Views.Public.class).writeValueAsString(data);
String full = om.writerWithView(Views.Internal.class).writeValueAsString(data);
pub: {"name":"..."}
full: {"name":"...","secret":"..."}
5) Сериализация JSON-дерева (JsonNode):
com.fasterxml.jackson.databind.node.ObjectNode node = new com.fasterxml.jackson.databind.node.ObjectNode(com.fasterxml.jackson.databind.node.JsonNodeFactory.instance);
node.put("x", 1);
String s = new ObjectMapper().writeValueAsString(node);
System.out.println(s);
{"x":1}
6) Полиморфная сериализация с безопасной валидацией:
ObjectMapper om = new ObjectMapper();
com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator ptv =
com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator.builder()
.allowIfBaseType("com.example.myapp")
.build();
om.activateDefaultTyping(ptv, com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping.NON_FINAL);
String s = om.writeValueAsString(List.of("a"));
System.out.println(s);
["a"] // при включённом default typing будут добавлены метаданные типов только для нестандартных случаев
7) Преобразование больших структур без выделения лишней памяти: использование ObjectWriter и потоков для записи прямо в OutputStream вместо получения строки, когда нужно избежать аллокации большой строки.
try (OutputStream os = new FileOutputStream("out.json")) {
new ObjectMapper().writer().writeValue(os, largeObject);
}
// Данные записаны в файл без получения одной огромной String
джава ObjectMapper.writeValueAsString function comments
- джава ObjectMapper.writeValueAsString - аргументы и возвращаемое значение
- Функция java ObjectMapper.writeValueAsString - описание
- ObjectMapper.writeValueAsString - примеры
- ObjectMapper.writeValueAsString - похожие методы на java
- ObjectMapper.writeValueAsString на javascript, c#, python, php
- ObjectMapper.writeValueAsString изменения java
- Примеры ObjectMapper.writeValueAsString на джава