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

如何用Jackson ObjectMapper序列化/反序列化大小写不敏感Map?

问题描述

使用Jackson的ObjectMapper序列化带有String.CASE_INSENSITIVE_ORDER比较器的TreeMap时,序列化后的JSON结构正常,但反序列化得到的TreeMap会丢失大小写不敏感的特性——比如无法通过小写键获取原有的大写键对应的值。

示例代码:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.TreeMap;

public class Main {
    public static void main(String[] args) throws JsonProcessingException {
        TreeMap<String, String> mappings = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        mappings.put("Test3", "3");
        mappings.put("test1", "1");
        mappings.put("Test2", "2");

        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(mappings);
        System.out.println(json);
        
        TreeMap<String, String> deserMappings = objectMapper.readValue(json, TreeMap.class);
        
        System.out.println("Deserialized map case insensitive test: " + deserMappings.get("test3"));
    }
}

示例输出:

{
  "test1" : "1",
  "Test2" : "2",
  "Test3" : "3"
}
Deserialized map case insensitive test: null

解决方案1:自定义反序列化器

创建一个TreeMap的反序列化器,强制用String.CASE_INSENSITIVE_ORDER初始化TreeMap,再将JSON中的键值对填充进去,最后注册到ObjectMapper中全局生效。

代码实现:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

import java.io.IOException;
import java.util.TreeMap;

// 自定义反序列化器
class CaseInsensitiveTreeMapDeserializer extends JsonDeserializer<TreeMap<String, String>> {
    @Override
    public TreeMap<String, String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        TreeMap<String, String> caseInsensitiveMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        caseInsensitiveMap.putAll(ctxt.readValue(p, TreeMap.class));
        return caseInsensitiveMap;
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) throws JsonProcessingException {
        TreeMap<String, String> mappings = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        mappings.put("Test3", "3");
        mappings.put("test1", "1");
        mappings.put("Test2", "2");

        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(TreeMap.class, new CaseInsensitiveTreeMapDeserializer());
        objectMapper.registerModule(module);

        String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(mappings);
        System.out.println(json);
        
        TreeMap<String, String> deserMappings = objectMapper.readValue(json, TreeMap.class);
        
        System.out.println("Deserialized map case insensitive test: " + deserMappings.get("test3")); // 输出3
    }
}

解决方案2:自定义大小写不敏感Map类

创建一个继承自TreeMap的子类,默认构造器中指定String.CASE_INSENSITIVE_ORDER比较器,反序列化时直接指定该类类型即可。

代码实现:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.TreeMap;

// 自定义大小写不敏感TreeMap
class CaseInsensitiveTreeMap extends TreeMap<String, String> {
    public CaseInsensitiveTreeMap() {
        super(String.CASE_INSENSITIVE_ORDER);
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) throws JsonProcessingException {
        CaseInsensitiveTreeMap mappings = new CaseInsensitiveTreeMap();
        mappings.put("Test3", "3");
        mappings.put("test1", "1");
        mappings.put("Test2", "2");

        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(mappings);
        System.out.println(json);
        
        CaseInsensitiveTreeMap deserMappings = objectMapper.readValue(json, CaseInsensitiveTreeMap.class);
        
        System.out.println("Deserialized map case insensitive test: " + deserMappings.get("test3")); // 输出3
    }
}

解决方案3:指定构造器参数(泛型场景适用)

如果需要处理泛型类型的大小写不敏感TreeMap,可以通过ObjectReader指定构造器参数,直接传入String.CASE_INSENSITIVE_ORDER来初始化TreeMap。

代码实现:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;

import java.util.TreeMap;

public class Main {
    public static void main(String[] args) throws JsonProcessingException {
        TreeMap<String, String> mappings = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        mappings.put("Test3", "3");
        mappings.put("test1", "1");
        mappings.put("Test2", "2");

        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(mappings);
        System.out.println(json);
        
        // 构造泛型类型并指定构造器参数
        TreeMap<String, String> deserMappings = objectMapper.readerFor(
                TypeFactory.defaultInstance().constructMapType(TreeMap.class, String.class, String.class)
        ).withCreatorConstructorArgs(String.CASE_INSENSITIVE_ORDER).readValue(json);
        
        System.out.println("Deserialized map case insensitive test: " + deserMappings.get("test3")); // 输出3
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:57:14