
本文介绍如何在java中为json解析器设计清晰、类型安全的值结构,通过继承体系替代通用object包装,实现asnumber()、asstring()等流畅api,提升类型安全性与可维护性。
本文介绍如何在java中为json解析器设计清晰、类型安全的值结构,通过继承体系替代通用object包装,实现asnumber()、asstring()等流畅api,提升类型安全性与可维护性。
在实现符合RFC 8259标准的JSON解析器时,核心挑战之一是如何统一建模JSON中七种互斥但语义明确的原始值类型(null、true、false、number、string、array、object)。若采用单一Value类并用Object字段承载所有值(如BigDecimal、String、Boolean等),虽看似简洁,却牺牲了编译期类型安全、可读性与扩展性——用户必须手动instanceof判断再强制转换,极易引发ClassCastException,且无法自然支持链式调用如parser.get("key").asNumber()。
更专业、主流且可扩展的设计是构建分层继承体系,以抽象基类JsonValue为根,为每种JSON原生类型定义具体子类:
// 根接口/抽象类,提供统一类型转换能力
public 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();
// 安全转换方法(失败时抛出JsonTypeException)
public String asString() {
if (!isString()) throw new JsonTypeException("Expected string, got " + getClass().getSimpleName());
return ((JsonString) this).getValue();
}
public int asInt() {
if (!isNumber()) throw new JsonTypeException("Expected number");
return ((JsonNumber) this).asInt();
}
public JsonObject asObject() {
if (!isObject()) throw new JsonTypeException("Expected object");
return (JsonObject) this;
}
public JsonArray asArray() {
if (!isArray()) throw new JsonTypeException("Expected array");
return (JsonArray) this;
}
}
// 具体实现示例
public final class JsonNull extends JsonValue {
public static final JsonNull INSTANCE = new JsonNull();
private JsonNull() {}
@Override public boolean isNull() { return true; }
@Override public String toString() { return "null"; }
}
public final class JsonBoolean extends JsonValue {
private final boolean value;
public JsonBoolean(boolean value) { this.value = value; }
@Override public boolean isBoolean() { return true; }
public boolean getValue() { return value; }
@Override public String toString() { return String.valueOf(value); }
}
public final class JsonString extends JsonValue {
private final String value;
public JsonString(String value) { this.value = value; }
@Override public boolean isString() { return true; }
public String getValue() { return value; }
@Override public String toString() { return "\"" + value + "\""; }
}
public final class JsonNumber extends JsonValue {
private final BigDecimal value;
public JsonNumber(BigDecimal value) { this.value = value; }
@Override public boolean isNumber() { return true; }
public BigDecimal getValue() { return value; }
public int asInt() { return value.intValueExact(); }
public double asDouble() { return value.doubleValue(); }
}
数组与对象类型同样继承JsonValue,并封装自身结构:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
public final class JsonArray extends JsonValue {
private final List<jsonvalue> elements = new ArrayList();
public void add(JsonValue element) { elements.add(element); }
public JsonValue get(int index) { return elements.get(index); }
public int size() { return elements.size(); }
@Override public boolean isArray() { return true; }
@Override public String toString() {
return "[" + elements.stream().map(Object::toString).collect(Collectors.joining(", ")) + "]";
}
}
public 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); }
public Set<string> keySet() { return members.keySet(); }
@Override public boolean isObject() { return true; }
@Override public String toString() {
return "{" + members.entrySet().stream()
.map(e -> "\"" + e.getKey() + "\": " + e.getValue())
.collect(Collectors.joining(", ")) + "}";
}
}</string></string></jsonvalue>
关键优势与注意事项:
✅ 类型安全:instanceof检查被封装在isXxx()方法中,转换逻辑集中可控;
✅ API友好:用户无需显式转型,直接调用asXXX()获得强类型结果;
✅ 可扩展性强:新增JSON类型(如RFC未来扩展)只需添加新子类,不修改现有逻辑;
✅ 语义清晰:每个类职责单一,符合单一职责原则,便于单元测试与调试。
⚠️ 避免陷阱:
- 不要将null、true、false作为字符串存储(如"null"),这会混淆JSON null与字符串"null";
- JsonNumber应使用BigDecimal而非double,确保精确表示JSON数字(如1.0000000000000001);
- JsonObject建议使用LinkedHashMap保持键顺序,符合RFC 7159“对象成员顺序应保留”的实践惯例。
该设计已被Jackson、Gson、org.json等主流库验证,既严格遵循JSON规范,又为开发者提供了直观、健壮、可维护的API体验。










