
本文介绍如何通过面向对象的继承结构,为JSON解析器构建类型安全、可扩展的Value抽象体系,避免运行时强制类型转换,支持链式调用如asObject()、asString()等语义化API。
本文介绍如何通过面向对象的继承结构,为json解析器构建类型安全、可扩展的value抽象体系,避免运行时强制类型转换,支持链式调用如`asobject()`、`asstring()`等语义化api。
在实现符合 RFC 8259 标准的 JSON 解析器时,核心挑战之一是如何统一建模 JSON 的七种原生类型(null、true、false、number、string、array、object),同时向用户提供类型明确、安全易用的访问接口(如 parser.get("key").asObject())。直接使用 Object 作为通用容器(如 private Object value;)虽简单,但牺牲了编译期类型检查,迫使用户频繁进行不安全的强制类型转换,极易引发 ClassCastException,且无法提供语义清晰的 API。
更优解是采用分层继承设计,以抽象基类 JsonValue 为根,为每种 JSON 类型定义专属子类:
// 抽象基类:统一入口,提供类型安全的转换方法
abstract class JsonValue {
public abstract boolean isNull();
public abstract boolean isBoolean();
public abstract boolean isNumber();
public abstract boolean isString();
public abstract boolean isArray();
public abstract boolean isObject();
// 安全转换方法(失败时抛出明确异常)
public JsonNull asNull() { throw new IllegalStateException("Not a null value"); }
public JsonBoolean asBoolean() { throw new IllegalStateException("Not a boolean value"); }
public JsonNumber asNumber() { throw new IllegalStateException("Not a number value"); }
public JsonString asString() { throw new IllegalStateException("Not a string value"); }
public JsonArray asArray() { throw new IllegalStateException("Not an array value"); }
public JsonObject asObject() { throw new IllegalStateException("Not an object value"); }
}
// 具体实现示例
final class JsonNull extends JsonValue {
@Override public boolean isNull() { return true; }
@Override public JsonNull asNull() { return this; }
@Override public String toString() { return "null"; }
}
final class JsonBoolean extends JsonValue {
private final boolean value;
JsonBoolean(boolean value) { this.value = value; }
@Override public boolean isBoolean() { return true; }
@Override public JsonBoolean asBoolean() { return this; }
public boolean getValue() { return value; }
@Override public String toString() { return String.valueOf(value); }
}
final class JsonObject extends JsonValue {
private final Map<string jsonvalue> members = new LinkedHashMap();
public void put(String key, JsonValue value) { members.put(key, value); }
public JsonValue get(String key) { return members.get(key); }
@Override public boolean isObject() { return true; }
@Override public JsonObject asObject() { return this; }
// 支持链式查询:parser.get("user").asObject().get("name").asString()
@Override public String toString() {
return "{" + members.entrySet().stream()
.map(e -> "\"" + e.getKey() + "\":" + e.getValue())
.collect(Collectors.joining(", ")) + "}";
}
}</string>
该设计带来三大关键优势:
- ✅ 类型安全:instanceof 检查与 asXxx() 方法均由编译器保障,错误在编译期或明确异常中暴露,而非运行时崩溃;
- ✅ 语义清晰:用户无需记忆底层类型映射(如 BigDecimal vs Long),asNumber() 统一返回 JsonNumber,其内部可封装 BigDecimal 或 Double;
- ✅ 扩展友好:新增类型(如 JsonBinary)仅需继承 JsonValue 并实现对应方法,不影响现有代码。
注意事项:
- 避免在 JsonValue 中存储原始 Java 类型(如 Object),这会破坏类型契约;
- 所有 asXxx() 方法应严格遵循“成功则返回实例,失败则抛异常”原则,禁止返回 null;
- toString() 实现需严格遵循 JSON 文本格式(如字符串加引号、null 小写),便于调试与序列化验证。
最终,用户可流畅使用如下 API:
JsonValue root = parser.parse("{\"users\":[{\"name\":\"Alice\"}]}");
JsonArray users = root.asObject().get("users").asArray();
String name = users.get(0).asObject().get("name").asString(); // "Alice"
这种设计既精准契合 RFC 8259 的语法定义,又将 JSON 的静态类型约束转化为 Java 的编译期契约,是构建健壮、可维护 JSON 工具库的工业级实践。











