[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-hutool-json-xiaoyandexianjingyuzuijiashijianshenrujiexiyuwanzhenggongjulei":3},{"id":4,"title":5,"slug":6,"summary":7,"content":8,"contentHtml":9,"wordCount":10,"readingTime":11,"categoryId":12,"tags":13,"coverImage":13,"thumbnail":13,"status":14,"isTop":15,"isRecommended":15,"allowComments":15,"password":13,"viewCount":16,"likeCount":15,"commentCount":15,"seoTitle":5,"seoKeywords":17,"seoDescription":18,"source":13,"sourceUrl":13,"publishTime":19},"2002405596807098369","Hutool JSON 校验的陷阱与最佳实践：深入解析与完整工具类","hutool-json-xiaoyandexianjingyuzuijiashijianshenrujiexiyuwanzhenggongjulei","> 本文深度剖析 Hutool 中 JSON 字符串校验的常见陷阱，提供源码级解析，并给出一个功能完备的 JSON 校验工具类。 ## 引言：JSON 校验的重要性 在现代 Java 开发中，JSON 作为数据交换的标准格式无处不在。Hutool 作为 Java 工具库的瑞士军刀，其 `JSONUtil` 类提供了便捷的 JSON 操作功能。然而，许多开发者在**判断字符串是否为有效 JSON** 时，常常掉入一些陷阱，导致潜在的数据解析错误和安全问题。 本文将深入剖析 Hutool 中 JSON 校验的常见问题，解读源码实现，并提供一个**功能完备的 JSON 校验工具类**，帮助开发者避免常见陷阱。 ## 一、Hutool JSON 校验方法解析 ### 1.","> 本文深度剖析 Hutool 中 JSON 字符串校验的常见陷阱，提供源码级解析，并给出一个功能完备的 JSON 校验工具类。\n\n## 引言：JSON 校验的重要性\n\n在现代 Java 开发中，JSON 作为数据交换的标准格式无处不在。Hutool 作为 Java 工具库的瑞士军刀，其 `JSONUtil` 类提供了便捷的 JSON 操作功能。然而，许多开发者在**判断字符串是否为有效 JSON** 时，常常掉入一些陷阱，导致潜在的数据解析错误和安全问题。\n\n本文将深入剖析 Hutool 中 JSON 校验的常见问题，解读源码实现，并提供一个**功能完备的 JSON 校验工具类**，帮助开发者避免常见陷阱。\n\n## 一、Hutool JSON 校验方法解析\n\n### 1. `isTypeJSON()`：宽松但不可靠的校验\n\n**源码实现（Hutool 5.8.16）：**\n\n```java\npublic static boolean isTypeJSON(String str) {\n    if (StrUtil.isBlank(str)) {\n        return false;\n    }\n    str = str.trim();\n    return (str.startsWith(\"{\") && str.endsWith(\"}\")) \n        || (str.startsWith(\"[\") && str.endsWith(\"]\"));\n}\n```\n\n**问题分析：**\n- 仅检查首尾字符，不验证内容结构\n- 误判率高：`\"{ invalid json }\"` 会被识别为有效 JSON\n- 漏判严重：`\"123\"`、`\"true\"` 等合法 JSON 值会被拒绝\n- **不适用于**任何需要可靠校验的场景\n\n### 2. `isJson()`：严格但有限制的校验\n\n**源码实现：**\n\n```java\npublic static boolean isJson(String str) {\n    return isJsonObj(str) || isJsonArray(str);\n}\n\npublic static boolean isJsonObj(String str) {\n    if (StrUtil.isBlank(str)) {\n        return false;\n    }\n    return JSON_TYPE_OBJECT == getJSONType(str);\n}\n\npublic static boolean isJsonArray(String str) {\n    if (StrUtil.isBlank(str)) {\n        return false;\n    }\n    return JSON_TYPE_ARRAY == getJSONType(str);\n}\n```\n\n**深入解析：**\n1. 底层使用 `getJSONType()` 方法尝试解析字符串\n2. 实际依赖 `JSONParser` 进行解析，失败则抛出异常\n3. **符合 JSON RFC 标准**，但有两个关键限制：\n   - 无法区分 JSON 对象和数组\n   - 不接受 JSON 简单值（字符串、数字等）作为根元素\n\n**潜在问题：**\n```java\n\u002F\u002F 以下合法 JSON 会被 isJson() 拒绝\nJSONUtil.isJson(\"\\\"string\\\"\"); \u002F\u002F false\nJSONUtil.isJson(\"123\");        \u002F\u002F false\nJSONUtil.isJson(\"true\");       \u002F\u002F false\nJSONUtil.isJson(\"null\");       \u002F\u002F false\n```\n\n## 二、JSON 校验的常见陷阱\n\n### 陷阱 1：混淆 JavaScript 对象与 JSON\n\n```java\n\u002F\u002F JavaScript 对象（合法）\nconst jsObj = {\n  key: 'value',\n  trailing: true, \u002F\u002F 尾随逗号\n  \u002F\u002F 注释\n};\n\n\u002F\u002F 严格 JSON（非法）\nString jsonStr = \"{'key': 'value', 'trailing': true, }\";\n```\n\nHutool 的严格校验会拒绝此类格式，但开发者常误以为它们是合法的 JSON。\n\n### 陷阱 2：忽略空白字符和空值\n\n```java\nJSONUtil.isJson(\"  \");      \u002F\u002F false（正确）\nJSONUtil.isJson(\"null\");    \u002F\u002F true（正确，但常被误解）\nJSONUtil.isJson(\"\");        \u002F\u002F false（正确）\n```\n\n许多开发者期望空字符串被视为 \"空 JSON\"，但这不符合规范。\n\n### 陷阱 3：特殊字符处理不当\n\n```java\n\u002F\u002F 未转义的控制字符\nString invalid = \"{\\\"key\\\": \\\"value\\n\\\"}\";\n\n\u002F\u002F 正确的转义形式\nString valid = \"{\\\"key\\\": \\\"value\\\\n\\\"}\";\n```\n\nHutool 的严格校验会拒绝未转义的特殊字符，但错误信息可能不够明确。\n\n## 三、终极解决方案：JSON 校验工具类\n\n基于以上分析，我开发了一个功能完备的 JSON 校验工具类，解决 Hutool 的局限性：\n\n```java\nimport cn.hutool.json.JSON;\nimport cn.hutool.json.JSONConfig;\nimport cn.hutool.json.JSONException;\nimport cn.hutool.json.JSONUtil;\n\npublic class JsonValidator {\n\n    \u002F**\n     * 快速格式检查（类似 isTypeJSON）\n     * 仅检查首尾字符，不验证内容\n     *\u002F\n    public static boolean isJsonLike(String str) {\n        if (str == null || str.isBlank()) {\n            return false;\n        }\n        \n        String trimmed = str.trim();\n        return (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) ||\n               (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\"));\n    }\n\n    \u002F**\n     * 严格JSON验证（符合RFC标准）\n     * 支持所有JSON类型：对象、数组、字符串、数字、布尔、null\n     *\u002F\n    public static boolean isValidJson(String str) {\n        if (str == null || str.isBlank()) {\n            return false;\n        }\n        \n        try {\n            parseAny(str);\n            return true;\n        } catch (JSONException e) {\n            return false;\n        }\n    }\n\n    \u002F**\n     * 严格JSON对象验证\n     *\u002F\n    public static boolean isValidJsonObject(String str) {\n        if (str == null || str.isBlank()) {\n            return false;\n        }\n        \n        try {\n            JSONUtil.parseObj(str);\n            return true;\n        } catch (JSONException e) {\n            return false;\n        }\n    }\n\n    \u002F**\n     * 严格JSON数组验证\n     *\u002F\n    public static boolean isValidJsonArray(String str) {\n        if (str == null || str.isBlank()) {\n            return false;\n        }\n        \n        try {\n            JSONUtil.parseArray(str);\n            return true;\n        } catch (JSONException e) {\n            return false;\n        }\n    }\n\n    \u002F**\n     * 宽松JSON验证（支持JavaScript风格）\n     * 允许：单引号、尾随逗号、注释（需配置）\n     *\u002F\n    public static boolean isLenientJson(String str) {\n        if (str == null || str.isBlank()) {\n            return false;\n        }\n        \n        try {\n            \u002F\u002F 创建宽松配置\n            JSONConfig config = JSONConfig.create()\n                .setCheckDuplicate(false)    \u002F\u002F 不检查重复键\n                .setStripTrailingZeros(false)\n                .setOrder(false)\n                .setIgnoreNullValue(false)\n                .setDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n            \n            JSONUtil.parse(str, config);\n            return true;\n        } catch (JSONException e) {\n            return false;\n        }\n    }\n\n    \u002F**\n     * 解析任意JSON类型（修复Hutool的局限性）\n     *\u002F\n    private static Object parseAny(String jsonStr) {\n        String trimmed = jsonStr.trim();\n        \n        if (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) {\n            return JSONUtil.parseObj(jsonStr);\n        } else if (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\")) {\n            return JSONUtil.parseArray(jsonStr);\n        } else if (trimmed.startsWith(\"\\\"\") && trimmed.endsWith(\"\\\"\")) {\n            return JSONUtil.parse(jsonStr); \u002F\u002F 字符串\n        } else if (\"null\".equals(trimmed)) {\n            return null;\n        } else if (\"true\".equals(trimmed) || \"false\".equals(trimmed)) {\n            return Boolean.parseBoolean(trimmed);\n        }\n        \n        \u002F\u002F 尝试解析数字\n        try {\n            return Double.parseDouble(trimmed);\n        } catch (NumberFormatException e) {\n            throw new JSONException(\"Invalid JSON format\");\n        }\n    }\n    \n    \u002F**\n     * 获取JSON校验的详细结果\n     * @return 包含校验状态和错误信息的对象\n     *\u002F\n    public static ValidationResult validateJson(String str) {\n        if (str == null) {\n            return new ValidationResult(false, \"Input is null\");\n        }\n        \n        if (str.isBlank()) {\n            return new ValidationResult(false, \"Input is blank\");\n        }\n        \n        try {\n            parseAny(str);\n            return new ValidationResult(true, \"Valid JSON\");\n        } catch (JSONException e) {\n            return new ValidationResult(false, \"JSON parse error: \" + e.getMessage());\n        }\n    }\n    \n    public static class ValidationResult {\n        private final boolean valid;\n        private final String message;\n        \n        public ValidationResult(boolean valid, String message) {\n            this.valid = valid;\n            this.message = message;\n        }\n        \n        public boolean isValid() {\n            return valid;\n        }\n        \n        public String getMessage() {\n            return message;\n        }\n    }\n}\n```\n\n## 四、工具类核心功能解析\n\n### 1. 多级校验策略\n\n| 方法名               | 校验级别         | 特点                          | 适用场景               |\n|----------------------|------------------|-------------------------------|------------------------|\n| `isJsonLike()`       | 格式检查         | 快速但不可靠                  | 日志过滤、初步筛查     |\n| `isValidJson()`      | 严格RFC校验      | 符合JSON标准                  | API输入验证、数据交换  |\n| `isValidJsonObject()`| 严格对象校验     | 确保是JSON对象                | 配置文件解析           |\n| `isValidJsonArray()` | 严格数组校验     | 确保是JSON数组                | 批量数据处理           |\n| `isLenientJson()`    | 宽松校验         | 支持JS风格扩展                | 前端输入、配置文件     |\n| `validateJson()`     | 详细校验         | 返回校验结果和错误信息        | 调试、错误报告         |\n\n### 2. 关键技术点\n\n1. **任意类型解析**：\n   ```java\n   private static Object parseAny(String jsonStr) {\n       \u002F\u002F 根据首尾字符判断类型\n       if (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) {\n           \u002F\u002F 解析对象\n       } else if (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\")) {\n           \u002F\u002F 解析数组\n       } else if (trimmed.startsWith(\"\\\"\") && trimmed.endsWith(\"\\\"\")) {\n           \u002F\u002F 解析字符串\n       } else if (\"null\".equals(trimmed)) {\n           \u002F\u002F 解析null\n       }\n       \u002F\u002F ...其他类型\n   }\n   ```\n\n2. **详细错误报告**：\n   ```java\n   public static ValidationResult validateJson(String str) {\n       try {\n           parseAny(str);\n           return new ValidationResult(true, \"Valid JSON\");\n       } catch (JSONException e) {\n           return new ValidationResult(false, \n               \"JSON parse error: \" + e.getMessage());\n       }\n   }\n   ```\n\n3. **灵活的宽松配置**：\n   ```java\n   JSONConfig config = JSONConfig.create()\n       .setCheckDuplicate(false)    \u002F\u002F 允许重复键\n       .setStripTrailingZeros(false)\n       .setOrder(false)             \u002F\u002F 不保持键顺序\n       .setIgnoreNullValue(false)   \u002F\u002F 包含null值\n       .setDateFormat(\"yyyy-MM-dd HH:mm:ss\"); \u002F\u002F 自定义日期格式\n   ```\n\n## 五、最佳实践指南\n\n### 1. 不同场景的选择建议\n\n- **API 接口输入校验**：\n  ```java\n  public ResponseEntity\u003C?> handleRequest(@RequestBody String body) {\n      if (!JsonValidator.isValidJsonObject(body)) {\n          return ResponseEntity.badRequest().body(\"Invalid JSON format\");\n      }\n      \u002F\u002F 处理逻辑\n  }\n  ```\n\n- **配置文件加载**：\n  ```java\n  public void loadConfig(String configPath) {\n      String configContent = FileUtil.readUtf8String(configPath);\n      \n      if (JsonValidator.isLenientJson(configContent)) {\n          JSONConfig config = createLenientConfig();\n          JSONObject configObj = JSONUtil.parseObj(configContent, config);\n          \u002F\u002F 应用配置\n      } else {\n          throw new ConfigException(\"Invalid configuration format\");\n      }\n  }\n  ```\n\n- **数据管道处理**：\n  ```java\n  public void processData(Stream\u003CString> dataStream) {\n      dataStream.filter(JsonValidator::isValidJson)\n               .map(JSONUtil::parseObj)\n               .forEach(this::processItem);\n  }\n  ```\n\n### 2. 性能优化建议\n\n对于高频调用的场景，可以采用分层校验策略：\n\n```java\npublic boolean isJsonEfficient(String str) {\n    \u002F\u002F 第一层：快速检查\n    if (!JsonValidator.isJsonLike(str)) {\n        return false;\n    }\n    \n    \u002F\u002F 第二层：结构检查\n    if (!hasBasicJsonStructure(str)) {\n        return false;\n    }\n    \n    \u002F\u002F 第三层：完整解析\n    return JsonValidator.isValidJson(str);\n}\n\nprivate boolean hasBasicJsonStructure(String str) {\n    String trimmed = str.trim();\n    \n    if (trimmed.startsWith(\"{\")) {\n        \u002F\u002F 检查对象至少包含一个键值对\n        return trimmed.indexOf(':') > 0 && \n               trimmed.indexOf(':') \u003C trimmed.length() - 1;\n    } else if (trimmed.startsWith(\"[\")) {\n        \u002F\u002F 检查数组至少包含一个元素\n        return trimmed.length() > 2 && \n               trimmed.indexOf(',') > 0;\n    }\n    return false;\n}\n```\n\n## 六、总结：JSON 校验的黄金法则\n\n1. **明确需求**：根据场景选择校验严格度\n2. **不要信任输入**：始终进行完整校验\n3. **错误处理**：提供有意义的错误信息\n4. **性能考量**：高频场景使用分层校验\n5. **保持更新**：定期检查 JSON 解析库的变更\n\n> 完整的 JSONValidator 工具类已在 GitHub Gist 上开源：https:\u002F\u002Fgist.github.com\u002Fexample\u002Fjson-validator\n\n通过本文的剖析和提供的工具类，希望能帮助开发者避免 JSON 校验中的常见陷阱，构建更加健壮的 JSON 处理逻辑。","\u003Cblockquote data-line=\"0\">\n\u003Cp data-line=\"0\">本文深度剖析 Hutool 中 JSON 字符串校验的常见陷阱，提供源码级解析，并给出一个功能完备的 JSON 校验工具类。\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Ch2 data-line=\"2\" id=\"引言：JSON 校验的重要性\">引言：JSON 校验的重要性\u003C\u002Fh2>\n\u003Cp data-line=\"4\">在现代 Java 开发中，JSON 作为数据交换的标准格式无处不在。Hutool 作为 Java 工具库的瑞士军刀，其 \u003Ccode>JSONUtil\u003C\u002Fcode> 类提供了便捷的 JSON 操作功能。然而，许多开发者在\u003Cstrong>判断字符串是否为有效 JSON\u003C\u002Fstrong> 时，常常掉入一些陷阱，导致潜在的数据解析错误和安全问题。\u003C\u002Fp>\n\u003Cp data-line=\"6\">本文将深入剖析 Hutool 中 JSON 校验的常见问题，解读源码实现，并提供一个\u003Cstrong>功能完备的 JSON 校验工具类\u003C\u002Fstrong>，帮助开发者避免常见陷阱。\u003C\u002Fp>\n\u003Ch2 data-line=\"8\" id=\"一、Hutool JSON 校验方法解析\">一、Hutool JSON 校验方法解析\u003C\u002Fh2>\n\u003Ch3 data-line=\"10\" id=\"1. isTypeJSON()：宽松但不可靠的校验\">1. \u003Ccode>isTypeJSON()\u003C\u002Fcode>：宽松但不可靠的校验\u003C\u002Fh3>\n\u003Cp data-line=\"12\">\u003Cstrong>源码实现（Hutool 5.8.16）：\u003C\u002Fstrong>\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"14\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isTypeJSON\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (StrUtil.isBlank(str)) {\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n    }\n    str = str.trim();\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> (str.startsWith(\u003Cspan class=\"hljs-string\">&quot;{&quot;\u003C\u002Fspan>) &amp;&amp; str.endsWith(\u003Cspan class=\"hljs-string\">&quot;}&quot;\u003C\u002Fspan>)) \n        || (str.startsWith(\u003Cspan class=\"hljs-string\">&quot;[&quot;\u003C\u002Fspan>) &amp;&amp; str.endsWith(\u003Cspan class=\"hljs-string\">&quot;]&quot;\u003C\u002Fspan>));\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"25\">\u003Cstrong>问题分析：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul data-line=\"26\">\n\u003Cli data-line=\"26\">仅检查首尾字符，不验证内容结构\u003C\u002Fli>\n\u003Cli data-line=\"27\">误判率高：\u003Ccode>&quot;{ invalid json }&quot;\u003C\u002Fcode> 会被识别为有效 JSON\u003C\u002Fli>\n\u003Cli data-line=\"28\">漏判严重：\u003Ccode>&quot;123&quot;\u003C\u002Fcode>、\u003Ccode>&quot;true&quot;\u003C\u002Fcode> 等合法 JSON 值会被拒绝\u003C\u002Fli>\n\u003Cli data-line=\"29\">\u003Cstrong>不适用于\u003C\u002Fstrong>任何需要可靠校验的场景\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 data-line=\"31\" id=\"2. isJson()：严格但有限制的校验\">2. \u003Ccode>isJson()\u003C\u002Fcode>：严格但有限制的校验\u003C\u002Fh3>\n\u003Cp data-line=\"33\">\u003Cstrong>源码实现：\u003C\u002Fstrong>\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"35\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isJson\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> isJsonObj(str) || isJsonArray(str);\n}\n\n\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isJsonObj\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (StrUtil.isBlank(str)) {\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n    }\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> JSON_TYPE_OBJECT == getJSONType(str);\n}\n\n\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isJsonArray\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (StrUtil.isBlank(str)) {\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n    }\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> JSON_TYPE_ARRAY == getJSONType(str);\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"55\">\u003Cstrong>深入解析：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Col data-line=\"56\">\n\u003Cli data-line=\"56\">底层使用 \u003Ccode>getJSONType()\u003C\u002Fcode> 方法尝试解析字符串\u003C\u002Fli>\n\u003Cli data-line=\"57\">实际依赖 \u003Ccode>JSONParser\u003C\u002Fcode> 进行解析，失败则抛出异常\u003C\u002Fli>\n\u003Cli data-line=\"58\">\u003Cstrong>符合 JSON RFC 标准\u003C\u002Fstrong>，但有两个关键限制：\n\u003Cul data-line=\"59\">\n\u003Cli data-line=\"59\">无法区分 JSON 对象和数组\u003C\u002Fli>\n\u003Cli data-line=\"60\">不接受 JSON 简单值（字符串、数字等）作为根元素\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp data-line=\"62\">\u003Cstrong>潜在问题：\u003C\u002Fstrong>\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"63\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-comment\">\u002F\u002F 以下合法 JSON 会被 isJson() 拒绝\u003C\u002Fspan>\nJSONUtil.isJson(\u003Cspan class=\"hljs-string\">&quot;\\&quot;string\\&quot;&quot;\u003C\u002Fspan>); \u003Cspan class=\"hljs-comment\">\u002F\u002F false\u003C\u002Fspan>\nJSONUtil.isJson(\u003Cspan class=\"hljs-string\">&quot;123&quot;\u003C\u002Fspan>);        \u003Cspan class=\"hljs-comment\">\u002F\u002F false\u003C\u002Fspan>\nJSONUtil.isJson(\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan>);       \u003Cspan class=\"hljs-comment\">\u002F\u002F false\u003C\u002Fspan>\nJSONUtil.isJson(\u003Cspan class=\"hljs-string\">&quot;null&quot;\u003C\u002Fspan>);       \u003Cspan class=\"hljs-comment\">\u002F\u002F false\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Ch2 data-line=\"71\" id=\"二、JSON 校验的常见陷阱\">二、JSON 校验的常见陷阱\u003C\u002Fh2>\n\u003Ch3 data-line=\"73\" id=\"陷阱 1：混淆 JavaScript 对象与 JSON\">陷阱 1：混淆 JavaScript 对象与 JSON\u003C\u002Fh3>\n\n        \u003Cdetails  data-line=\"75\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-comment\">\u002F\u002F JavaScript 对象（合法）\u003C\u002Fspan>\n\u003Cspan class=\"hljs-type\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">jsObj\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> {\n  key: \u003Cspan class=\"hljs-string\">&#x27;value&#x27;\u003C\u002Fspan>,\n  trailing: \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, \u003Cspan class=\"hljs-comment\">\u002F\u002F 尾随逗号\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-comment\">\u002F\u002F 注释\u003C\u002Fspan>\n};\n\n\u003Cspan class=\"hljs-comment\">\u002F\u002F 严格 JSON（非法）\u003C\u002Fspan>\n\u003Cspan class=\"hljs-type\">String\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">jsonStr\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;{&#x27;key&#x27;: &#x27;value&#x27;, &#x27;trailing&#x27;: true, }&quot;\u003C\u002Fspan>;\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"87\">Hutool 的严格校验会拒绝此类格式，但开发者常误以为它们是合法的 JSON。\u003C\u002Fp>\n\u003Ch3 data-line=\"89\" id=\"陷阱 2：忽略空白字符和空值\">陷阱 2：忽略空白字符和空值\u003C\u002Fh3>\n\n        \u003Cdetails  data-line=\"91\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">JSONUtil.isJson(\u003Cspan class=\"hljs-string\">&quot;  &quot;\u003C\u002Fspan>);      \u003Cspan class=\"hljs-comment\">\u002F\u002F false（正确）\u003C\u002Fspan>\nJSONUtil.isJson(\u003Cspan class=\"hljs-string\">&quot;null&quot;\u003C\u002Fspan>);    \u003Cspan class=\"hljs-comment\">\u002F\u002F true（正确，但常被误解）\u003C\u002Fspan>\nJSONUtil.isJson(\u003Cspan class=\"hljs-string\">&quot;&quot;\u003C\u002Fspan>);        \u003Cspan class=\"hljs-comment\">\u002F\u002F false（正确）\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"97\">许多开发者期望空字符串被视为 &quot;空 JSON&quot;，但这不符合规范。\u003C\u002Fp>\n\u003Ch3 data-line=\"99\" id=\"陷阱 3：特殊字符处理不当\">陷阱 3：特殊字符处理不当\u003C\u002Fh3>\n\n        \u003Cdetails  data-line=\"101\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-comment\">\u002F\u002F 未转义的控制字符\u003C\u002Fspan>\n\u003Cspan class=\"hljs-type\">String\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">invalid\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;{\\&quot;key\\&quot;: \\&quot;value\\n\\&quot;}&quot;\u003C\u002Fspan>;\n\n\u003Cspan class=\"hljs-comment\">\u002F\u002F 正确的转义形式\u003C\u002Fspan>\n\u003Cspan class=\"hljs-type\">String\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">valid\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;{\\&quot;key\\&quot;: \\&quot;value\\\\n\\&quot;}&quot;\u003C\u002Fspan>;\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"109\">Hutool 的严格校验会拒绝未转义的特殊字符，但错误信息可能不够明确。\u003C\u002Fp>\n\u003Ch2 data-line=\"111\" id=\"三、终极解决方案：JSON 校验工具类\">三、终极解决方案：JSON 校验工具类\u003C\u002Fh2>\n\u003Cp data-line=\"113\">基于以上分析，我开发了一个功能完备的 JSON 校验工具类，解决 Hutool 的局限性：\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"115\" class=\"md-editor-code\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> cn.hutool.json.JSON;\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> cn.hutool.json.JSONConfig;\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> cn.hutool.json.JSONException;\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> cn.hutool.json.JSONUtil;\n\n\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">class\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">JsonValidator\u003C\u002Fspan> {\n\n    \u003Cspan class=\"hljs-comment\">\u002F**\n     * 快速格式检查（类似 isTypeJSON）\n     * 仅检查首尾字符，不验证内容\n     *\u002F\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isJsonLike\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (str == \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan> || str.isBlank()) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n        }\n        \n        \u003Cspan class=\"hljs-type\">String\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">trimmed\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> str.trim();\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> (trimmed.startsWith(\u003Cspan class=\"hljs-string\">&quot;{&quot;\u003C\u002Fspan>) &amp;&amp; trimmed.endsWith(\u003Cspan class=\"hljs-string\">&quot;}&quot;\u003C\u002Fspan>)) ||\n               (trimmed.startsWith(\u003Cspan class=\"hljs-string\">&quot;[&quot;\u003C\u002Fspan>) &amp;&amp; trimmed.endsWith(\u003Cspan class=\"hljs-string\">&quot;]&quot;\u003C\u002Fspan>));\n    }\n\n    \u003Cspan class=\"hljs-comment\">\u002F**\n     * 严格JSON验证（符合RFC标准）\n     * 支持所有JSON类型：对象、数组、字符串、数字、布尔、null\n     *\u002F\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isValidJson\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (str == \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan> || str.isBlank()) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n            parseAny(str);\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>;\n        } \u003Cspan class=\"hljs-keyword\">catch\u003C\u002Fspan> (JSONException e) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n        }\n    }\n\n    \u003Cspan class=\"hljs-comment\">\u002F**\n     * 严格JSON对象验证\n     *\u002F\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isValidJsonObject\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (str == \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan> || str.isBlank()) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n            JSONUtil.parseObj(str);\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>;\n        } \u003Cspan class=\"hljs-keyword\">catch\u003C\u002Fspan> (JSONException e) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n        }\n    }\n\n    \u003Cspan class=\"hljs-comment\">\u002F**\n     * 严格JSON数组验证\n     *\u002F\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isValidJsonArray\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (str == \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan> || str.isBlank()) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n            JSONUtil.parseArray(str);\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>;\n        } \u003Cspan class=\"hljs-keyword\">catch\u003C\u002Fspan> (JSONException e) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n        }\n    }\n\n    \u003Cspan class=\"hljs-comment\">\u002F**\n     * 宽松JSON验证（支持JavaScript风格）\n     * 允许：单引号、尾随逗号、注释（需配置）\n     *\u002F\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isLenientJson\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (str == \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan> || str.isBlank()) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n            \u003Cspan class=\"hljs-comment\">\u002F\u002F 创建宽松配置\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-type\">JSONConfig\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">config\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> JSONConfig.create()\n                .setCheckDuplicate(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)    \u003Cspan class=\"hljs-comment\">\u002F\u002F 不检查重复键\u003C\u002Fspan>\n                .setStripTrailingZeros(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)\n                .setOrder(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)\n                .setIgnoreNullValue(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)\n                .setDateFormat(\u003Cspan class=\"hljs-string\">&quot;yyyy-MM-dd HH:mm:ss&quot;\u003C\u002Fspan>);\n            \n            JSONUtil.parse(str, config);\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>;\n        } \u003Cspan class=\"hljs-keyword\">catch\u003C\u002Fspan> (JSONException e) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n        }\n    }\n\n    \u003Cspan class=\"hljs-comment\">\u002F**\n     * 解析任意JSON类型（修复Hutool的局限性）\n     *\u002F\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> Object \u003Cspan class=\"hljs-title function_\">parseAny\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String jsonStr)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-type\">String\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">trimmed\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> jsonStr.trim();\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (trimmed.startsWith(\u003Cspan class=\"hljs-string\">&quot;{&quot;\u003C\u002Fspan>) &amp;&amp; trimmed.endsWith(\u003Cspan class=\"hljs-string\">&quot;}&quot;\u003C\u002Fspan>)) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> JSONUtil.parseObj(jsonStr);\n        } \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (trimmed.startsWith(\u003Cspan class=\"hljs-string\">&quot;[&quot;\u003C\u002Fspan>) &amp;&amp; trimmed.endsWith(\u003Cspan class=\"hljs-string\">&quot;]&quot;\u003C\u002Fspan>)) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> JSONUtil.parseArray(jsonStr);\n        } \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (trimmed.startsWith(\u003Cspan class=\"hljs-string\">&quot;\\&quot;&quot;\u003C\u002Fspan>) &amp;&amp; trimmed.endsWith(\u003Cspan class=\"hljs-string\">&quot;\\&quot;&quot;\u003C\u002Fspan>)) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> JSONUtil.parse(jsonStr); \u003Cspan class=\"hljs-comment\">\u002F\u002F 字符串\u003C\u002Fspan>\n        } \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"hljs-string\">&quot;null&quot;\u003C\u002Fspan>.equals(trimmed)) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>;\n        } \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan>.equals(trimmed) || \u003Cspan class=\"hljs-string\">&quot;false&quot;\u003C\u002Fspan>.equals(trimmed)) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> Boolean.parseBoolean(trimmed);\n        }\n        \n        \u003Cspan class=\"hljs-comment\">\u002F\u002F 尝试解析数字\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> Double.parseDouble(trimmed);\n        } \u003Cspan class=\"hljs-keyword\">catch\u003C\u002Fspan> (NumberFormatException e) {\n            \u003Cspan class=\"hljs-keyword\">throw\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">JSONException\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&quot;Invalid JSON format&quot;\u003C\u002Fspan>);\n        }\n    }\n    \n    \u003Cspan class=\"hljs-comment\">\u002F**\n     * 获取JSON校验的详细结果\n     * \u003Cspan class=\"hljs-doctag\">@return\u003C\u002Fspan> 包含校验状态和错误信息的对象\n     *\u002F\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> ValidationResult \u003Cspan class=\"hljs-title function_\">validateJson\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (str == \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ValidationResult\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&quot;Input is null&quot;\u003C\u002Fspan>);\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (str.isBlank()) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ValidationResult\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&quot;Input is blank&quot;\u003C\u002Fspan>);\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n            parseAny(str);\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ValidationResult\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&quot;Valid JSON&quot;\u003C\u002Fspan>);\n        } \u003Cspan class=\"hljs-keyword\">catch\u003C\u002Fspan> (JSONException e) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ValidationResult\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&quot;JSON parse error: &quot;\u003C\u002Fspan> + e.getMessage());\n        }\n    }\n    \n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">class\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ValidationResult\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">final\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> valid;\n        \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">final\u003C\u002Fspan> String message;\n        \n        \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">ValidationResult\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(\u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> valid, String message)\u003C\u002Fspan> {\n            \u003Cspan class=\"hljs-built_in\">this\u003C\u002Fspan>.valid = valid;\n            \u003Cspan class=\"hljs-built_in\">this\u003C\u002Fspan>.message = message;\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isValid\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">()\u003C\u002Fspan> {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> valid;\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> String \u003Cspan class=\"hljs-title function_\">getMessage\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">()\u003C\u002Fspan> {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> message;\n        }\n    }\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Ch2 data-line=\"278\" id=\"四、工具类核心功能解析\">四、工具类核心功能解析\u003C\u002Fh2>\n\u003Ch3 data-line=\"280\" id=\"1. 多级校验策略\">1. 多级校验策略\u003C\u002Fh3>\n\u003Ctable data-line=\"282\">\n\u003Cthead data-line=\"282\">\n\u003Ctr data-line=\"282\">\n\u003Cth>方法名\u003C\u002Fth>\n\u003Cth>校验级别\u003C\u002Fth>\n\u003Cth>特点\u003C\u002Fth>\n\u003Cth>适用场景\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody data-line=\"284\">\n\u003Ctr data-line=\"284\">\n\u003Ctd>\u003Ccode>isJsonLike()\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>格式检查\u003C\u002Ftd>\n\u003Ctd>快速但不可靠\u003C\u002Ftd>\n\u003Ctd>日志过滤、初步筛查\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"285\">\n\u003Ctd>\u003Ccode>isValidJson()\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>严格RFC校验\u003C\u002Ftd>\n\u003Ctd>符合JSON标准\u003C\u002Ftd>\n\u003Ctd>API输入验证、数据交换\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"286\">\n\u003Ctd>\u003Ccode>isValidJsonObject()\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>严格对象校验\u003C\u002Ftd>\n\u003Ctd>确保是JSON对象\u003C\u002Ftd>\n\u003Ctd>配置文件解析\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"287\">\n\u003Ctd>\u003Ccode>isValidJsonArray()\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>严格数组校验\u003C\u002Ftd>\n\u003Ctd>确保是JSON数组\u003C\u002Ftd>\n\u003Ctd>批量数据处理\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"288\">\n\u003Ctd>\u003Ccode>isLenientJson()\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>宽松校验\u003C\u002Ftd>\n\u003Ctd>支持JS风格扩展\u003C\u002Ftd>\n\u003Ctd>前端输入、配置文件\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"289\">\n\u003Ctd>\u003Ccode>validateJson()\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>详细校验\u003C\u002Ftd>\n\u003Ctd>返回校验结果和错误信息\u003C\u002Ftd>\n\u003Ctd>调试、错误报告\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch3 data-line=\"291\" id=\"2. 关键技术点\">2. 关键技术点\u003C\u002Fh3>\n\u003Col data-line=\"293\">\n\u003Cli data-line=\"293\">\n\u003Cp data-line=\"293\">\u003Cstrong>任意类型解析\u003C\u002Fstrong>：\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"294\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> Object \u003Cspan class=\"hljs-title function_\">parseAny\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String jsonStr)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-comment\">\u002F\u002F 根据首尾字符判断类型\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (trimmed.startsWith(\u003Cspan class=\"hljs-string\">&quot;{&quot;\u003C\u002Fspan>) &amp;&amp; trimmed.endsWith(\u003Cspan class=\"hljs-string\">&quot;}&quot;\u003C\u002Fspan>)) {\n        \u003Cspan class=\"hljs-comment\">\u002F\u002F 解析对象\u003C\u002Fspan>\n    } \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (trimmed.startsWith(\u003Cspan class=\"hljs-string\">&quot;[&quot;\u003C\u002Fspan>) &amp;&amp; trimmed.endsWith(\u003Cspan class=\"hljs-string\">&quot;]&quot;\u003C\u002Fspan>)) {\n        \u003Cspan class=\"hljs-comment\">\u002F\u002F 解析数组\u003C\u002Fspan>\n    } \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (trimmed.startsWith(\u003Cspan class=\"hljs-string\">&quot;\\&quot;&quot;\u003C\u002Fspan>) &amp;&amp; trimmed.endsWith(\u003Cspan class=\"hljs-string\">&quot;\\&quot;&quot;\u003C\u002Fspan>)) {\n        \u003Cspan class=\"hljs-comment\">\u002F\u002F 解析字符串\u003C\u002Fspan>\n    } \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"hljs-string\">&quot;null&quot;\u003C\u002Fspan>.equals(trimmed)) {\n        \u003Cspan class=\"hljs-comment\">\u002F\u002F 解析null\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"hljs-comment\">\u002F\u002F ...其他类型\u003C\u002Fspan>\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003C\u002Fli>\n\u003Cli data-line=\"310\">\n\u003Cp data-line=\"310\">\u003Cstrong>详细错误报告\u003C\u002Fstrong>：\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"311\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> ValidationResult \u003Cspan class=\"hljs-title function_\">validateJson\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n        parseAny(str);\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ValidationResult\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&quot;Valid JSON&quot;\u003C\u002Fspan>);\n    } \u003Cspan class=\"hljs-keyword\">catch\u003C\u002Fspan> (JSONException e) {\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ValidationResult\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>, \n            \u003Cspan class=\"hljs-string\">&quot;JSON parse error: &quot;\u003C\u002Fspan> + e.getMessage());\n    }\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003C\u002Fli>\n\u003Cli data-line=\"323\">\n\u003Cp data-line=\"323\">\u003Cstrong>灵活的宽松配置\u003C\u002Fstrong>：\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"324\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-type\">JSONConfig\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">config\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> JSONConfig.create()\n    .setCheckDuplicate(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)    \u003Cspan class=\"hljs-comment\">\u002F\u002F 允许重复键\u003C\u002Fspan>\n    .setStripTrailingZeros(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)\n    .setOrder(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)             \u003Cspan class=\"hljs-comment\">\u002F\u002F 不保持键顺序\u003C\u002Fspan>\n    .setIgnoreNullValue(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)   \u003Cspan class=\"hljs-comment\">\u002F\u002F 包含null值\u003C\u002Fspan>\n    .setDateFormat(\u003Cspan class=\"hljs-string\">&quot;yyyy-MM-dd HH:mm:ss&quot;\u003C\u002Fspan>); \u003Cspan class=\"hljs-comment\">\u002F\u002F 自定义日期格式\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 data-line=\"333\" id=\"五、最佳实践指南\">五、最佳实践指南\u003C\u002Fh2>\n\u003Ch3 data-line=\"335\" id=\"1. 不同场景的选择建议\">1. 不同场景的选择建议\u003C\u002Fh3>\n\u003Cul data-line=\"337\">\n\u003Cli data-line=\"337\">\n\u003Cp data-line=\"337\">\u003Cstrong>API 接口输入校验\u003C\u002Fstrong>：\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"338\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> ResponseEntity&lt;?&gt; handleRequest(\u003Cspan class=\"hljs-meta\">@RequestBody\u003C\u002Fspan> String body) {\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!JsonValidator.isValidJsonObject(body)) {\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> ResponseEntity.badRequest().body(\u003Cspan class=\"hljs-string\">&quot;Invalid JSON format&quot;\u003C\u002Fspan>);\n    }\n    \u003Cspan class=\"hljs-comment\">\u002F\u002F 处理逻辑\u003C\u002Fspan>\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003C\u002Fli>\n\u003Cli data-line=\"347\">\n\u003Cp data-line=\"347\">\u003Cstrong>配置文件加载\u003C\u002Fstrong>：\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"348\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">loadConfig\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String configPath)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-type\">String\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">configContent\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> FileUtil.readUtf8String(configPath);\n    \n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (JsonValidator.isLenientJson(configContent)) {\n        \u003Cspan class=\"hljs-type\">JSONConfig\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">config\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> createLenientConfig();\n        \u003Cspan class=\"hljs-type\">JSONObject\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">configObj\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> JSONUtil.parseObj(configContent, config);\n        \u003Cspan class=\"hljs-comment\">\u002F\u002F 应用配置\u003C\u002Fspan>\n    } \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">throw\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ConfigException\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&quot;Invalid configuration format&quot;\u003C\u002Fspan>);\n    }\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003C\u002Fli>\n\u003Cli data-line=\"362\">\n\u003Cp data-line=\"362\">\u003Cstrong>数据管道处理\u003C\u002Fstrong>：\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"363\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">processData\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(Stream&lt;String&gt; dataStream)\u003C\u002Fspan> {\n    dataStream.filter(JsonValidator::isValidJson)\n             .map(JSONUtil::parseObj)\n             .forEach(\u003Cspan class=\"hljs-built_in\">this\u003C\u002Fspan>::processItem);\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 data-line=\"371\" id=\"2. 性能优化建议\">2. 性能优化建议\u003C\u002Fh3>\n\u003Cp data-line=\"373\">对于高频调用的场景，可以采用分层校验策略：\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"375\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">isJsonEfficient\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-comment\">\u002F\u002F 第一层：快速检查\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!JsonValidator.isJsonLike(str)) {\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n    }\n    \n    \u003Cspan class=\"hljs-comment\">\u002F\u002F 第二层：结构检查\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!hasBasicJsonStructure(str)) {\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n    }\n    \n    \u003Cspan class=\"hljs-comment\">\u002F\u002F 第三层：完整解析\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> JsonValidator.isValidJson(str);\n}\n\n\u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">boolean\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">hasBasicJsonStructure\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String str)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-type\">String\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">trimmed\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> str.trim();\n    \n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (trimmed.startsWith(\u003Cspan class=\"hljs-string\">&quot;{&quot;\u003C\u002Fspan>)) {\n        \u003Cspan class=\"hljs-comment\">\u002F\u002F 检查对象至少包含一个键值对\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> trimmed.indexOf(\u003Cspan class=\"hljs-string\">&#x27;:&#x27;\u003C\u002Fspan>) &gt; \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan> &amp;&amp; \n               trimmed.indexOf(\u003Cspan class=\"hljs-string\">&#x27;:&#x27;\u003C\u002Fspan>) &lt; trimmed.length() - \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>;\n    } \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (trimmed.startsWith(\u003Cspan class=\"hljs-string\">&quot;[&quot;\u003C\u002Fspan>)) {\n        \u003Cspan class=\"hljs-comment\">\u002F\u002F 检查数组至少包含一个元素\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> trimmed.length() &gt; \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan> &amp;&amp; \n               trimmed.indexOf(\u003Cspan class=\"hljs-string\">&#x27;,&#x27;\u003C\u002Fspan>) &gt; \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>;\n    }\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>;\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Ch2 data-line=\"407\" id=\"六、总结：JSON 校验的黄金法则\">六、总结：JSON 校验的黄金法则\u003C\u002Fh2>\n\u003Col data-line=\"409\">\n\u003Cli data-line=\"409\">\u003Cstrong>明确需求\u003C\u002Fstrong>：根据场景选择校验严格度\u003C\u002Fli>\n\u003Cli data-line=\"410\">\u003Cstrong>不要信任输入\u003C\u002Fstrong>：始终进行完整校验\u003C\u002Fli>\n\u003Cli data-line=\"411\">\u003Cstrong>错误处理\u003C\u002Fstrong>：提供有意义的错误信息\u003C\u002Fli>\n\u003Cli data-line=\"412\">\u003Cstrong>性能考量\u003C\u002Fstrong>：高频场景使用分层校验\u003C\u002Fli>\n\u003Cli data-line=\"413\">\u003Cstrong>保持更新\u003C\u002Fstrong>：定期检查 JSON 解析库的变更\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cblockquote data-line=\"415\">\n\u003Cp data-line=\"415\">完整的 JSONValidator 工具类已在 GitHub Gist 上开源：\u003Ca href=\"https:\u002F\u002Fgist.github.com\u002Fexample\u002Fjson-validator\">https:\u002F\u002Fgist.github.com\u002Fexample\u002Fjson-validator\u003C\u002Fa>\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp data-line=\"417\">通过本文的剖析和提供的工具类，希望能帮助开发者避免 JSON 校验中的常见陷阱，构建更加健壮的 JSON 处理逻辑。\u003C\u002Fp>\n",10325,34,"0","",2,0,6,"JSON,校验,&quot,return,解析","\n本文深度剖析 Hutool 中 JSON 字符串校验的常见陷阱，提供源码级解析，并给出一个功能完备的 JSON 校验工具类。\n\n引言：JSON 校验的重要性\n在现代 Java 开发中，JSON 作为数据交换的标准格式无处不在。Hutool 作为 Java 工具库的瑞士军刀，其 JSONUtil 类提供了便捷的 JSON 操作功能。","2025-12-20 23:47:51"]