如何将Jackson对象属性序列化为转义JSON字符串?
如何在Jackson中实现对象到转义JSON字符串的泛型序列化(无需新建ObjectMapper)
问题分析
你需要将对象序列化为转义后的JSON字符串作为属性值,但当前实现新建了ObjectMapper,这会导致配置不一致(比如丢失已注册的模块、序列化特性),同时也不够高效。
解决方案:复用现有SerializerProvider配置
可以通过SerializerProvider获取目标类型的序列化器,将对象序列化到临时缓冲区,再将结果作为转义字符串写入最终的JsonGenerator,完全复用原有配置。
基础泛型序列化器实现
class ObjectAsEscapedStringSerializer<T> : JsonSerializer<T>() { override fun serialize(value: T, gen: JsonGenerator, serializers: SerializerProvider) { // 获取当前对象类型对应的序列化器 val valueSerializer = serializers.findValueSerializer(value.javaClass) // 创建临时Writer捕获序列化结果 val stringWriter = StringWriter() // 基于现有配置创建临时JsonGenerator val tempGenerator = serializers.codec.factory.createGenerator(stringWriter) // 执行序列化到临时缓冲区 valueSerializer.serialize(value, tempGenerator, serializers) tempGenerator.close() // 将捕获的JSON字符串作为转义后的字符串写入目标生成器 gen.writeString(stringWriter.toString()) } }
支持泛型参数化类型的增强实现
如果目标类型是带泛型参数的(比如List<AType>),可以通过createContextual方法获取正确的类型信息:
class ObjectAsEscapedStringSerializer<T> : JsonSerializer<T>() { private var valueSerializer: JsonSerializer<T>? = null override fun createContextual(prov: SerializerProvider, property: BeanProperty?): JsonSerializer<*> { // 获取当前属性的具体类型 val targetType = property?.type ?: throw IllegalArgumentException("无法获取属性类型信息") // 获取对应类型的序列化器 val serializer = prov.findValueSerializer(targetType) as JsonSerializer<T> val newSerializer = ObjectAsEscapedStringSerializer<T>() newSerializer.valueSerializer = serializer return newSerializer } override fun serialize(value: T, gen: JsonGenerator, serializers: SerializerProvider) { val serializer = valueSerializer ?: throw IllegalStateException("序列化器未初始化") val stringWriter = StringWriter() val tempGenerator = serializers.codec.factory.createGenerator(stringWriter) serializer.serialize(value, tempGenerator, serializers) tempGenerator.close() gen.writeString(stringWriter.toString()) } }
方案优势
- 配置一致性:完全复用当前
SerializerProvider的配置(比如已注册的JavaTimeModule、日期序列化特性等),避免新建ObjectMapper导致的行为差异。 - 性能更优:不需要重复创建
ObjectMapper实例,减少资源开销。 - 泛型支持:增强版实现可以处理带泛型参数的复杂类型。
使用方式
和你原来的用法一致,直接在属性上添加注解:
class MyClass( @field:JsonSerialize(using = ObjectAsEscapedStringSerializer::class) val value : AType )
内容的提问来源于stack exchange,提问作者Roque Sosa
相关产品推荐
相关产品推荐

