You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中Jackson空键序列化配置无效,报keySerializer为null错误

解决Jackson序列化含空键Map时的keySerializer为null错误

问题描述

序列化包含空键的Map对象时触发以下错误:

Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Cannot invoke "com.fasterxml.jackson.databind.JsonSerializer.serialize(Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)" because "keySerializer" is null]

尝试注册Jackson自定义配置类(如下)但未生效:

@Bean
fun jsonCustomizer(): Jackson2ObjectMapperBuilderCustomizer =
    Jackson2ObjectMapperBuilderCustomizer { builder: Jackson2ObjectMapperBuilder ->
        builder.postConfigurer { objectMapper: ObjectMapper ->
            objectMapper
                .serializerProvider
                .setNullKeySerializer(
                    object : JsonSerializer<Any>() {
                        override fun serialize(
                            value: Any,
                            gen: JsonGenerator,
                            serializers: SerializerProvider,
                        ) {
                            gen.writeFieldName("")
                        }
                    },
                )
        }
    }

补充详细错误栈:

com.fasterxml.jackson.databind.JsonMappingException: Cannot invoke "com.fasterxml.jackson.databind.JsonSerializer.serialize(Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)" because "keySerializer" is null (引用链:java.util.ArrayList[0]->com.example.MyOuterFoo["outerFooKey"]->com.example.SecondFoo["secondFooKey"]->java.util.Arrays$ArrayList[0]->com.example.InnerFoo["innerFooKey"]->java.util.LinkedHashMap["hashMapKey"])

问题原因

直接修改objectMapper.serializerProvider的nullKeySerializer不生效,因为Jackson的SerializerProvider实例通常是不可变的,修改现有实例不会影响后续序列化使用的Provider对象。

解决方案

方案1:创建新的SerializerProvider实例替换原有对象

通过创建新的SerializerProvider实例并设置到ObjectMapper中,确保空键序列化配置生效:

@Bean
fun jsonCustomizer(): Jackson2ObjectMapperBuilderCustomizer =
    Jackson2ObjectMapperBuilderCustomizer { builder ->
        builder.postConfigurer { objectMapper ->
            // 创建新的SerializerProvider实例
            val serializerProvider = objectMapper.serializerProvider
                .createInstance(objectMapper.serializationConfig, objectMapper.serializerFactory)
            
            // 设置空键序列化器
            serializerProvider.setNullKeySerializer(object : JsonSerializer<Any>() {
                override fun serialize(value: Any, gen: JsonGenerator, serializers: SerializerProvider) {
                    // 将空键序列化为空字符串
                    gen.writeFieldName("")
                }
            })
            
            // 替换ObjectMapper的SerializerProvider
            objectMapper.setSerializerProvider(serializerProvider)
        }
    }

方案2:通过SimpleModule注册全局键序列化器

注册一个自定义的键序列化器,统一处理空键和常规键的序列化:

@Bean
fun jsonCustomizer(): Jackson2ObjectMapperBuilderCustomizer =
    Jackson2ObjectMapperBuilderCustomizer { builder ->
        builder.modules(object : SimpleModule() {
            init {
                addKeySerializer(Any::class.java, object : JsonSerializer<Any>() {
                    override fun serialize(value: Any?, gen: JsonGenerator, serializers: SerializerProvider) {
                        if (value == null) {
                            // 空键序列化为空字符串
                            gen.writeFieldName("")
                        } else {
                            // 非空键使用默认序列化逻辑
                            serializers.defaultSerializeKey(value, gen)
                        }
                    }
                })
            }
        })
    }

验证说明

两种方案都能确保Jackson在序列化含空键的Map时,不会出现keySerializer为null的错误,同时将空键序列化为指定的空字符串(可根据需求修改writeFieldName的参数)。

内容的提问来源于stack exchange,提问作者pixel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 17:30:57