如何用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
相关产品推荐
相关产品推荐

