咨询JSON解析器类结构优化:实现无强制转换的类型访问API
JSON解析器类结构设计优化问题
我正在开发一款基础JSON字符串解析器,遵循RFC 8259规范,其中:
- Section 3 定义JSON值:
value = false / null / true / object / array / number / string
- Section 4 定义JSON对象:
object = begin-object [ member *( value-separator member ) ]
end-objectmember = string name-separator value
目前已实现的Java类结构如下:
private static class Value { private java.lang.Object object; @Override public String toString() { String string; if (object instanceof Boolean) string = (boolean) object ? "true" : "false"; else if (object instanceof BigDecimal) string = ((BigDecimal) object).toPlainString(); else if (object instanceof String) string = (String) object; else string = object.toString(); return string; } }
private static class Object { List<Member> list = new ArrayList<>(); private static class Member { private String name; private List<Value> value; @Override public String toString() { return "{" + name + ": " + value + "}"; } } @Override public String toString() { return list.toString(); } }
我希望优化存储JSON值的方式,实现类似以下伪代码的API,避免用户手动强制转换Java Object:
parser.get("key").asString(); parser.get(0).asArray(); parser.get(1).asObject(); parser.findObject("key").asObject(); parser.findNumber(123).asNumber();
请问有什么合适的设计理念或方案可以实现这一需求?
优化方案:基于抽象基类的多态设计
核心思路
采用抽象基类+具体类型子类的设计,将每种JSON值类型封装为独立子类,通过多态实现类型安全的转换方法,同时提供统一的访问入口,彻底避免强制类型转换。
具体实现步骤
1. 定义抽象基类 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(); // 直接转换方法,类型不匹配时抛出明确异常 public JsonNull asNull() { throw new IllegalStateException("当前值不是null类型"); } public Boolean asBoolean() { throw new IllegalStateException("当前值不是布尔类型"); } public BigDecimal asNumber() { throw new IllegalStateException("当前值不是数字类型"); } public String asString() { throw new IllegalStateException("当前值不是字符串类型"); } public JsonArray asArray() { throw new IllegalStateException("当前值不是数组类型"); } public JsonObject asObject() { throw new IllegalStateException("当前值不是对象类型"); } // 安全转换方法,返回Optional避免空指针 public Optional<JsonNull> asOptionalNull() { return Optional.empty(); } public Optional<Boolean> asOptionalBoolean() { return Optional.empty(); } public Optional<BigDecimal> asOptionalNumber() { return Optional.empty(); } public Optional<String> asOptionalString() { return Optional.empty(); } public Optional<JsonArray> asOptionalArray() { return Optional.empty(); } public Optional<JsonObject> asOptionalObject() { return Optional.empty(); } }
2. 实现各具体类型子类
针对每种JSON值类型实现子类,重写对应方法:
- JsonNull:处理null值
public class JsonNull extends JsonValue { @Override public boolean isNull() { return true; } @Override public boolean isBoolean() { return false; } @Override public boolean isNumber() { return false; } @Override public boolean isString() { return false; } @Override public boolean isArray() { return false; } @Override public boolean isObject() { return false; } @Override public JsonNull asNull() { return this; } @Override public Optional<JsonNull> asOptionalNull() { return Optional.of(this); } @Override public String toString() { return "null"; } }
- JsonBoolean:处理布尔值
public class JsonBoolean extends JsonValue { private final boolean value; public JsonBoolean(boolean value) { this.value = value; } @Override public boolean isBoolean() { return true; } @Override public boolean isNull() { return false; } @Override public boolean isNumber() { return false; } @Override public boolean isString() { return false; } @Override public boolean isArray() { return false; } @Override public boolean isObject() { return false; } @Override public Boolean asBoolean() { return value; } @Override public Optional<Boolean> asOptionalBoolean() { return Optional.of(value); } @Override public String toString() { return Boolean.toString(value); } }
- JsonNumber:处理数字
public class JsonNumber extends JsonValue { private final BigDecimal value; public JsonNumber(BigDecimal value) { this.value = value; } @Override public boolean isNumber() { return true; } @Override public boolean isNull() { return false; } @Override public boolean isBoolean() { return false; } @Override public boolean isString() { return false; } @Override public boolean isArray() { return false; } @Override public boolean isObject() { return false; } @Override public BigDecimal asNumber() { return value; } @Override public Optional<BigDecimal> asOptionalNumber() { return Optional.of(value); } @Override public String toString() { return value.toPlainString(); } }
- JsonString:处理字符串
public class JsonString extends JsonValue { private final String value; public JsonString(String value) { this.value = value; } @Override public boolean isString() { return true; } @Override public boolean isNull() { return false; } @Override public boolean isBoolean() { return false; } @Override public boolean isNumber() { return false; } @Override public boolean isArray() { return false; } @Override public boolean isObject() { return false; } @Override public String asString() { return value; } @Override public Optional<String> asOptionalString() { return Optional.of(value); } @Override public String toString() { return "\"" + value + "\""; } }
- JsonArray:处理数组
public class JsonArray extends JsonValue { private final List<JsonValue> elements; public JsonArray(List<JsonValue> elements) { this.elements = new ArrayList<>(elements); } @Override public boolean isArray() { return true; } @Override public boolean isNull() { return false; } @Override public boolean isBoolean() { return false; } @Override public boolean isNumber() { return false; } @Override public boolean isString() { return false; } @Override public boolean isObject() { return false; } @Override public JsonArray asArray() { return this; } @Override public Optional<JsonArray> asOptionalArray() { return Optional.of(this); } // 数组访问方法 public JsonValue get(int index) { return elements.get(index); } public int size() { return elements.size(); } @Override public String toString() { StringBuilder sb = new StringBuilder("["); for (int i = 0; i < elements.size(); i++) { if (i > 0) sb.append(", "); sb.append(elements.get(i).toString()); } sb.append("]"); return sb.toString(); } }
- JsonObject:处理对象
public class JsonObject extends JsonValue { private final Map<String, JsonValue> members; public JsonObject(Map<String, JsonValue> members) { this.members = new HashMap<>(members); } @Override public boolean isObject() { return true; } @Override public boolean isNull() { return false; } @Override public boolean isBoolean() { return false; } @Override public boolean isNumber() { return false; } @Override public boolean isString() { return false; } @Override public boolean isArray() { return false; } @Override public JsonObject asObject() { return this; } @Override public Optional<JsonObject> asOptionalObject() { return Optional.of(this); } // 对象访问方法 public JsonValue get(String key) { return members.get(key); } public boolean containsKey(String key) { return members.containsKey(key); } public Set<String> keySet() { return members.keySet(); } @Override public String toString() { StringBuilder sb = new StringBuilder("{"); int i = 0; for (Map.Entry<String, JsonValue> entry : members.entrySet()) { if (i > 0) sb.append(", "); sb.append("\"").append(entry.getKey()).append("\": ").append(entry.getValue().toString()); i++; } sb.append("}"); return sb.toString(); } }
3. 实现Parser类的目标API
基于上述类结构,实现用户期望的类型安全API:
public class JsonParser { private final JsonValue rootValue; public JsonParser(JsonValue rootValue) { this.rootValue = rootValue; } // 从根对象获取指定key的值 public JsonValue get(String key) { if (rootValue.isObject()) { return rootValue.asObject().get(key); } throw new IllegalStateException("根值不是JSON对象"); } // 从根数组获取指定索引的值 public JsonValue get(int index) { if (rootValue.isArray()) { return rootValue.asArray().get(index); } throw new IllegalStateException("根值不是JSON数组"); } // 查找并返回指定key的对象 public JsonObject findObject(String key) { JsonValue value = get(key); if (value.isObject()) { return value.asObject(); } throw new IllegalStateException("key '" + key + "' 对应的值不是JSON对象"); } // 查找匹配数字的值(示例逻辑,可扩展为递归遍历) public JsonNumber findNumber(BigDecimal target) { if (rootValue.isNumber() && rootValue.asNumber().equals(target)) { return (JsonNumber) rootValue; } throw new IllegalArgumentException("未找到匹配的数字值"); } }
补充建议
- 优先使用
Optional版本的转换方法,减少空指针异常; - 可添加访问者模式扩展功能,比如自定义序列化、验证逻辑;
- 针对类型不匹配的场景,抛出带有明确上下文的异常,方便用户调试。
内容的提问来源于stack exchange,提问作者Reilas
相关产品推荐
相关产品推荐

