You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

咨询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-object

member = 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 06:45:15