Android中如何比较并合并大小写不同的同名JSON键?
这个问题太常见了——JSON键的大小写不敏感合并确实是日常开发里容易踩的坑,我给你几个实用的解决方案,分场景给你讲清楚:
核心思路
本质上就是要忽略键的大小写差异,先建立一个统一的匹配规则(比如全部转成小写作为匹配标识),然后把API响应里的值对应到预期JSON的键上,嵌套的JSON也可以递归处理。
方案1:基于org.json库(Java)
如果你用的是Java生态里最常用的org.json.JSONObject,可以自己封装一个工具方法来处理,逻辑清晰还灵活:
import org.json.JSONObject; public class JsonCaseInsensitiveMerge { public static void merge(JSONObject targetJson, JSONObject sourceJson) { // 先把目标JSON的键转成小写映射,方便快速查找 JSONObject lowerCaseKeyMap = new JSONObject(); for (String targetKey : targetJson.keySet()) { lowerCaseKeyMap.put(targetKey.toLowerCase(), targetKey); } // 遍历API响应的每个键 for (String sourceKey : sourceJson.keySet()) { String lowerSourceKey = sourceKey.toLowerCase(); // 检查目标JSON里有没有匹配的键(大小写不敏感) if (lowerCaseKeyMap.has(lowerSourceKey)) { String targetKey = lowerCaseKeyMap.getString(lowerSourceKey); Object sourceValue = sourceJson.get(sourceKey); // 如果是嵌套的JSONObject,递归合并 if (sourceValue instanceof JSONObject && targetJson.get(targetKey) instanceof JSONObject) { merge((JSONObject) targetJson.get(targetKey), (JSONObject) sourceValue); } else { // 直接覆盖目标键的值,也可以根据需求改成追加逻辑 targetJson.put(targetKey, sourceValue); } } else { // 可选:如果API返回的键在目标里不存在,要不要新增?按需开启 // targetJson.put(sourceKey, sourceValue); } } } }
用法示例
// 你原本预期的JSONObject JSONObject expected = new JSONObject("{\"Name\":\"Alice\",\"Age\":30,\"Contact\":{\"Email\":\"alice@test.com\"}}"); // API返回的响应JSON JSONObject apiResponse = new JSONObject("{\"name\":\"Alice Smith\",\"age\":31,\"contact\":{\"phone\":\"123456789\"}}"); // 执行合并 JsonCaseInsensitiveMerge.merge(expected, apiResponse); // 打印合并后的结果 System.out.println(expected.toString(2));
输出结果会保留你预期的键名,同时覆盖/合并API返回的值:
{ "Name": "Alice Smith", "Age": 31, "Contact": { "Email": "alice@test.com", "phone": "123456789" } }
方案2:基于Jackson库(Java)
如果你的项目用Jackson处理JSON,那可以利用它的配置特性来简化操作,不用自己写遍历逻辑:
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; public class JacksonMergeDemo { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); // 关键配置:开启大小写不敏感的属性匹配 mapper.configure(DeserializationFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); String expectedJson = "{\"Name\":\"Alice\",\"Age\":30,\"Contact\":{\"Email\":\"alice@test.com\"}}"; String apiJson = "{\"name\":\"Alice Smith\",\"age\":31,\"contact\":{\"phone\":\"123456789\"}}"; // 先把预期JSON转成实体类对象 User user = mapper.readValue(expectedJson, User.class); // 用API响应的JSON更新这个对象(自动匹配大小写不敏感的属性) mapper.readerForUpdating(user).readValue(apiJson); // 再转回JSON,得到合并后的结果 String mergedJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user); System.out.println(mergedJson); } // 对应你的JSON结构的实体类(可以用Lombok简化getter/setter) static class User { private String Name; private int Age; private Contact Contact; // 省略getter和setter,或者用@Data注解 public String getName() { return Name; } public void setName(String name) { Name = name; } public int getAge() { return Age; } public void setAge(int age) { Age = age; } public Contact getContact() { return Contact; } public void setContact(Contact contact) { Contact = contact; } static class Contact { private String Email; private String phone; public String getEmail() { return Email; } public void setEmail(String email) { Email = email; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } } } }
通用思路(其他语言)
不管你用Python、JavaScript还是其他语言,核心步骤都是一样的:
- 第一步:遍历目标JSON的所有键,建立一个「小写键 → 原键名」的映射表
- 第二步:遍历API响应的每个键,转成小写后去映射表找对应的目标键
- 第三步:如果找到匹配的键,就把API的值赋值给目标键;如果是嵌套JSON,递归处理
- 可选:如果API的键在目标里没有匹配,根据需求决定是否新增这个键
比如Python的简单实现示例:
import json def merge_case_insensitive(target, source): # 建立目标键的小写映射 lower_key_map = {k.lower(): k for k in target} for source_key, source_val in source.items(): lower_source_key = source_key.lower() if lower_source_key in lower_key_map: target_key = lower_key_map[lower_source_key] # 递归处理嵌套字典 if isinstance(source_val, dict) and isinstance(target.get(target_key), dict): merge_case_insensitive(target[target_key], source_val) else: target[target_key] = source_val else: # 可选:新增不存在的键 # target[source_key] = source_val pass # 测试 expected = json.loads('{"Name":"Alice","Age":30,"Contact":{"Email":"alice@test.com"}}') api_response = json.loads('{"name":"Alice Smith","age":31,"contact":{"phone":"123456789"}}') merge_case_insensitive(expected, api_response) print(json.dumps(expected, indent=2))
内容的提问来源于stack exchange,提问作者Malhotra
相关产品推荐
相关产品推荐

