在C++开发中,判断字符串是否为合法JSON格式是数据校验环节的常见需求,既可以借助正则表达式实现轻量校验,也可以使用成熟的第三方库完成精准验证。

正则校验的实现思路与局限
正则表达式可以快速匹配JSON的基础结构,适合对校验精度要求不高的场景。JSON的基础结构包含对象、数组、字符串、数字、布尔值和null,我们可以先编写匹配这些基础元素的规则。
基础正则规则说明
JSON的核心结构规则如下:
- 对象由
{开头,}结尾,内部是键值对,键是字符串,值可以是任意JSON类型 - 数组由
[开头,]结尾,内部是多个JSON值用逗号分隔 - 字符串由双引号包裹,内部可以包含转义字符
- 数字支持整数、小数、指数形式
- 布尔值只有
true和false,空值用null表示
正则校验代码示例
以下是使用C++标准库<regex>实现的基础JSON校验代码:
#include <iostream>
#include <regex>
#include <string>
// 基础JSON正则规则,仅覆盖简单场景
const std::string JSON_REGEX = R"(
^(
{ // 对象开头
(
"[^"\]*(?:\.[^"\]*)*" // 字符串键
s*:s* // 冒号分隔
(
"[^"\]*(?:\.[^"\]*)*" // 字符串值
| -?d+(.d+)?([eE][+-]?d+)? // 数字
| true | false | null // 布尔和空值
| [.*] // 数组
| {.*} // 嵌套对象
)
(,s* // 逗号分隔多个键值对
"[^"\]*(?:\.[^"\]*)*"
s*:s*
(
"[^"\]*(?:\.[^"\]*)*"
| -?d+(.d+)?([eE][+-]?d+)?
| true | false | null
| [.*]
| {.*}
)
)*
)?
}
| [ // 数组开头
(
(
"[^"\]*(?:\.[^"\]*)*"
| -?d+(.d+)?([eE][+-]?d+)?
| true | false | null
| [.*]
| {.*}
)
(,s*
(
"[^"\]*(?:\.[^"\]*)*"
| -?d+(.d+)?([eE][+-]?d+)?
| true | false | null
| [.*]
| {.*}
)
)*
)?
]
)$
)";
bool is_valid_json_by_regex(const std::string& str) {
try {
// 去除字符串首尾空白
std::string trimmed = str;
trimmed.erase(0, trimmed.find_first_not_of(" tnrfv"));
trimmed.erase(trimmed.find_last_not_of(" tnrfv") + 1);
// 正则匹配,忽略空白字符
std::regex pattern(JSON_REGEX, std::regex::extended | std::regex::icase);
return std::regex_match(trimmed, pattern);
} catch (const std::regex_error& e) {
std::cerr << "正则错误: " << e.what() << std::endl;
return false;
}
}
int main() {
std::string test1 = "{"name":"test","age":18}";
std::string test2 = "[1,2,3,true]";
std::string test3 = "invalid json";
std::cout << test1 << " 是否合法: " << (is_valid_json_by_regex(test1) ? "是" : "否") << std::endl;
std::cout << test2 << " 是否合法: " << (is_valid_json_by_regex(test2) ? "是" : "否") << std::endl;
std::cout << test3 << " 是否合法: " << (is_valid_json_by_regex(test3) ? "是" : "否") << std::endl;
return 0;
}
需要注意的是,正则校验无法覆盖所有JSON规范场景,比如复杂的嵌套结构、特殊转义字符、Unicode编码等场景容易出现误判,仅适合简单场景的快速校验。
使用jsoncpp库精准校验
如果需要高精度的JSON合法性校验,推荐使用成熟的第三方库jsoncpp,它可以完整支持JSON规范的所有特性,校验结果更准确。
环境准备
首先需要安装jsoncpp库,在Ubuntu系统可以通过sudo apt-get install libjsoncpp-dev安装,其他系统可以从源码编译安装。
校验代码示例
以下是使用jsoncpp判断字符串是否为合法JSON的代码:
#include <iostream>
#include <string>
#include <json/json.h>
bool is_valid_json_by_jsoncpp(const std::string& str) {
Json::CharReaderBuilder readerBuilder;
Json::Value root;
std::string errs;
// 从字符串解析JSON,解析成功则格式合法
std::istringstream iss(str);
if (Json::parseFromStream(readerBuilder, iss, &root, &errs)) {
return true;
} else {
std::cerr << "JSON解析错误: " << errs << std::endl;
return false;
}
}
int main() {
std::string test1 = "{"name":"张三","age":20,"hobby":["篮球","读书"]}";
std::string test2 = "{"name":"李四","age":null}";
std::string test3 = "{"name":"王五",age:25}"; // 键没有双引号,非法
std::cout << test1 << " 是否合法: " << (is_valid_json_by_jsoncpp(test1) ? "是" : "否") << std::endl;
std::cout << test2 << " 是否合法: " << (is_valid_json_by_jsoncpp(test2) ? "是" : "否") << std::endl;
std::cout << test3 << " 是否合法: " << (is_valid_json_by_jsoncpp(test3) ? "是" : "否") << std::endl;
return 0;
}
两种方案的选择建议
如果项目对JSON校验的要求不高,仅需要过滤明显格式错误的字符串,正则校验实现简单,不需要引入额外依赖,适合轻量场景。如果项目需要严格遵循JSON规范,处理复杂的JSON结构,优先选择jsoncpp这类成熟的第三方库,避免正则校验的局限性导致的问题。
| 校验方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 正则校验 | 无额外依赖,实现简单 | 无法覆盖所有JSON规范,容易误判 | 简单场景快速校验 |
| jsoncpp库校验 | 符合JSON规范,校验精准 | 需要引入第三方依赖 | 严格JSON格式校验场景 |