1.3 核心概念
JSONMap 是什么
JSONMap 继承 HashMap<String, Object>,在保留 Map 所有功能的基础上,增加了深层路径访问、自动类型转换、链式构建能力。
核心能力:
- 深层路径访问:用
user.profile.city穿透任意层级,路径不存在返回 null - 智能层级构建:
set("a.b.c", 1)自动创建中间 Map 对象 - 自动类型转换:
getInt("age")自动将"25"转为25 - 链式操作:每个方法返回
this
解决的核心问题
判空地狱
// 传统方式:每层判空 + 强转
String city = null;
if (data != null && data.get("user") != null) {
Map user = (Map) data.get("user");
if (user.get("profile") != null) {
Map profile = (Map) user.get("profile");
city = (String) profile.get("city");
}
}
// JSONMap
String city = new JSONMap(data).getStr("user.profile.city");
类型转换
// 传统方式:instanceof 判断 + 手动转换
Integer age = null;
Object ageObj = data.get("age");
if (ageObj instanceof String) age = Integer.parseInt((String) ageObj);
else if (ageObj instanceof Integer) age = (Integer) ageObj;
else if (ageObj instanceof Long) age = ((Long) ageObj).intValue();
// JSONMap
Integer age = new JSONMap(data).getInt("age");
构建嵌套结构
// 传统方式:层层 new HashMap
Map<String, Object> config = new HashMap<>();
Map<String, Object> server = new HashMap<>();
server.put("host", "localhost");
config.put("server", server);
// JSONMap
JSONMap config = new JSONMap().set("server.host", "localhost");
核心设计理念:有界宽容原则
- 缺失容忍:路径不存在返回 null,不抛异常
- 类型容忍:类型不同但能转换(
"25"→ 25) - 内容不容忍:内容无法转换时抛异常(
"abc"→ int 抛异常)
JSONMap data = new JSONMap();
// 缺失容忍
String name = data.getStr("user.name"); // null,不会 NPE
// 类型容忍
data.put("age", "25");
Integer age = data.getInt("age"); // 25
// 内容不容忍
data.put("age", "abc");
data.getInt("age"); // 抛出异常
// 推荐:提供默认值
Integer age = data.getInt("age", 0);
详见 4.4 有界宽容原则。
零侵入设计
JSONMap 继承 HashMap,完全兼容 Map 接口:
// 可以当普通 Map 使用
Map<String, Object> map = new JSONMap();
map.put("key", "value");
// 也可以使用增强功能
JSONMap jsonMap = (JSONMap) map;
String str = jsonMap.getStr("key");
适用场景
推荐使用:
- API 响应解析(嵌套深的结构)
- 动态构建请求体
- 配置文件处理
- 表单数据处理
- 数据转换和清洗
谨慎使用:
- 数据结构固定且简单,直接用 HashMap 即可
- 需要严格类型检查的场景
最佳实践
// 1. 优先使用路径表达式
String name = data.getStr("user.profile.name");
// 2. 提供默认值
int age = data.getInt("user.age", 0);
// 3. 使用链式操作
JSONMap request = new JSONMap()
.set("header.token", token)
.set("body.data", data);
// 4. 区分 put 和 set
json.put("a.b", 1); // {"a.b": 1} — key 不解析
json.set("a.b", 1); // {"a": {"b": 1}} — key 解析为路径