让C++处理JSON类型配置文件更轻松-Hjson-cpp详解

  • 一、Hjson-Cpp简介
    • Hjson-Cpp简介
    • 核心特性
    • 安装与集成
    • 基本用法示例
    • 常用API说明
    • 与JSON互转
    • 错误处理
    • 性能建议
    • 高级特性
      • 1. 类型安全访问
      • 2. 文件操作
      • 3. 自定义解析规则
  • 二、使用教程
    • 下载
    • 使用

一、Hjson-Cpp简介

Hjson-Cpp简介

Hjson-Cpp是C++实现的Hjson解析库。Hjson(Human JSON)是JSON的扩展格式,支持注释、多行字符串等更友好的语法,适用于配置文件等场景。Hjson-Cpp提供将Hjson转换为JSON或直接解析为C++对象的功能。

  • 支持注释:单行(//)和多行(/* */)注释
  • 宽松语法:字符串可以不加引号,末尾逗号可省略
  • 多行字符串:更自然的文本块表示
  • 更友好的错误提示:定位配置错误更直观

核心特性

  • 支持标准Hjson语法,包括注释(#//)、无引号键名、多行字符串。
  • 提供与JSON互转的能力,兼容现有JSON工具链。
  • 轻量级实现,仅依赖C++11标准库。

安装与集成

使用CMake集成Hjson-cpp:

find_package(hjsoncpp REQUIRED)
target_link_libraries(your_target PRIVATE hjsoncpp)

或手动下载源码后,将include/hjson目录添加到项目头文件路径。

基本用法示例

解析Hjson字符串并读取内容:

#include <hjson/hjson.h>
#include <iostream>
#include <fstream>int main() {// 从字符串解析std::string configStr = R"(// 这是一个Hjson配置示例{appName: My Application  // 字符串可以不加引号version: 1.2.3features: ["fast-mode"  // 引号也是允许的dark-theme   // 这种写法也可以auto-save    // 最后一个元素可以不加逗号]/* 多行注释 */timeout: 30s  // 带单位的数值})";Hjson::Value config;try {config = Hjson::Unmarshal(configStr);// 访问数据std::cout << "App: " << config["appName"].to_string() << "\n";std::cout << "Version: " << config["version"].to_double() << "\n";// 遍历数组std::cout << "Features:\n";for (auto& feature : config["features"]) {std::cout << " - " << feature.to_string() << "\n";}} catch (Hjson::syntax_error& e) {std::cerr << "配置语法错误: " << e.what() << "\n";return1;}return0;
}

常用API说明

  • Hjson::Marshal(value):将C++对象序列化为Hjson字符串。
  • Hjson::Unmarshal(text):解析Hjson文本为Hjson::Value对象。
  • value.to_string()/to_int():类型转换方法。
  • value[key]:访问对象成员或数组元素。

与JSON互转

将JSON转为Hjson(保留注释等扩展特性):

Hjson::Value jsonData = Hjson::Unmarshal(jsonText);
std::string hjsonText = Hjson::Marshal(jsonData);

错误处理

解析失败时抛出Hjson::syntax_error异常:

try {Hjson::Unmarshal("invalid hjson");
} catch (const Hjson::syntax_error& e) {std::cerr << "Error: " << e.what() << "\n";
}

性能建议

  • 对于大型文件,优先使用UnmarshalFromFile直接读取文件。
  • 频繁操作时可复用Hjson::Value对象减少内存分配。

高级特性

1. 类型安全访问

// 安全获取配置值(带默认值)
std::string appName = config.get("appName", "Default App");
int timeout = config.get("timeout", 10);  // 自动类型转换// 检查类型
if (config["features"].type() == Hjson::Type::Vector) {std::cout << "features是数组类型\n";
}// 类型转换方法
double version = config["version"].to_double();
std::string versionStr = config["version"].to_string();  // 自动转换

2. 文件操作

// 从文件加载配置
try {Hjson::Value fileConfig = Hjson::UnmarshalFromFile("config.hjson");// 修改配置fileConfig["lastRun"] = Hjson::Value(time(nullptr));// 写回文件(保留注释和格式)Hjson::MarshalToFile(fileConfig, "config.hjson");
} catch (Hjson::file_error& e) {std::cerr << "文件操作失败: " << e.what() << "\n";
}

3. 自定义解析规则

// 解析带单位的数值
Hjson::DecoderOptions options;
options.unitResolver = [](const std::string& unit, double value) {if (unit == "s") return value * 1000;  // 秒转毫秒if (unit == "min") return value * 60 * 1000;return value;
};Hjson::Value customConfig = Hjson::Unmarshal("timeout: 30s", options);
std::cout << "Timeout in ms: " << customConfig["timeout"].to_int64() << "\n";

二、使用教程

下载

点击https://github.com/hjson/hjson-cpp跳转到github:
在这里插入图片描述

点击Download下载源码。

在这里插入图片描述
或在文章顶部下载。

使用

VS新建工程:
在这里插入图片描述
拷贝Hjson源码进入工程目录:
在这里插入图片描述
编写测试代码:

#include <iostream>
#include "hjson.h"using namespace std;static const char* _szDefaultConfig = R"(
{imageSource: NO DEFAULTshowImages: truewriteImages: trueprintFrameIndex: falseprintFrameRate: true
}
)";Hjson::Value GetConfig(const char* szConfigPath) {Hjson::Value defaultConfig = Hjson::Unmarshal(_szDefaultConfig);Hjson::Value inputConfig;try {inputConfig = Hjson::UnmarshalFromFile(szConfigPath);}catch (const std::exception& e) {std::fprintf(stderr, "Error in config: %s\n\n", e.what());std::fprintf(stdout, "Default config:\n");std::fprintf(stdout, _szDefaultConfig);return Hjson::Value();}return Hjson::Merge(defaultConfig, inputConfig);
}int main()
{string path = "C:\\Users\\徐鹏\\Desktop\\hjson\\test.json";Hjson::Value val = GetConfig(path.c_str());printf("%s\r\n",val["imageSource"].to_string().c_str());Hjson::Value a = val.at("showImages");printf("%d\r\n", a.to_int64());return 0;
}

运行查看结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/84041.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/84041.shtml
英文地址,请注明出处:http://en.pswp.cn/web/84041.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单例模式的好处

为什么要使用单例模式 1.资源管理&#xff1a; 唯一性&#xff1a;某些资源在整个应用程序中只需要一个实例&#xff0c;例如日志记录器、配置管理器、数据库连接池等。单例模式可以确保这些资源的唯一性&#xff0c;避免重复创建和管理。 全局访问&#xff1a;单例模式提供了…

LangChain 结构化输出指南

LangChain 结构化输出指南 概述 对于许多应用程序&#xff08;如聊天机器人&#xff09;&#xff0c;模型需要直接用自然语言回应用户。然而&#xff0c;在某些场景下&#xff0c;我们需要模型以结构化格式输出。例如&#xff0c;我们可能希望将模型输出存储在数据库中&#…

探究webView与html的通讯

最近出来个新需求&#xff1a; 需求描述&#xff1a; 将uniapp的代码打包成一个app&#xff0c;并实现原本的功能。 原uniapp是一个H5项目&#xff0c;主要的步骤流程是上传用户的身份证进行二要素认证&#xff0c;成功后再进行三方活体认证&#xff0c;然后三方回跳到项目中的…

高级定时器TIM1、TIM8

高级定时器在通用定时器的基础上增加了一些功能&#xff0c;如&#xff1a;重复计数器、带死区控制的互补输出通道、断路输入等。 捕获/比较通道的输出部分(通道1至3) 捕获/比较通道的输出部分(通道4) ①重复计数器RCR 基本和通用定时器发生溢出时&#xff0c;会直接生成更新时…

搭建简易采购系统:从需求分析到供应商数据库设计

一、需求分析框架&#xff08;4大核心模块&#xff09; 关键需求清单&#xff1a; 需求提报&#xff08;含审批流&#xff09; 供应商准入与评估 比价与订单生成 基础报表功能 二、技术选型方案 组件推荐方案替代方案前端框架Vue.js ElementUIReact Ant Design后端语言P…

基于LSTM-GARCH混合模型的“获利了结”量化解析:黄金单日1.27%跌幅的技术性归因

摘要&#xff1a;本文通过多维度量化指标、结合地缘风险溢价因子、货币政策预期指数及贸易摩擦不确定性指数&#xff0c;构建动态情景分析框架。 一、黄金价格技术面解析 周一&#xff08;6月16日&#xff09;现货黄金呈现"冲高回落-获利了结"典型特征&#xff0c;日…

【AI】Spring AI Alibaba 的介绍

目录 一、Spring AI Alibaba 的介绍 1.1 什么是 Spring AI Alibaba&#xff1f; 1.2 Spring AI 项目简介 二、核心概念 2.1 模型 2.2 提示&#xff08;Prompt&#xff09; 2.3 提示词模板&#xff08;Prompt Template&#xff09; 2.4 嵌入&#xff08;Embedding&#x…

从main()函数的执行发散开来

大多数程序员的第一行代码可能都是从输出“Hello&#xff0c;World!开始的吧。如果请你写一个c程序&#xff0c;在屏幕上打印“Hello&#xff0c;World!”&#xff0c;下面的代码对拥有扎实编程基本功的你而言肯定so easy&#xff1a; #include <stdio.h>int main() {pr…

(16)java+ selenium->自动化测试-元素定位之By xpath下篇

1.简介 老规矩,我们还是接着前面两篇的Xpath 5.自动测试实战 以百度首页为例,将xpath的各种定位方法一一讲解和分享一下。 5.1大致步骤 1.访问百度首页。 2.通过xpath定位到元素,点击一下。 5.2模糊定位starts-with关键字 有一种特殊的情况:页面元素的属性值会被动态…

45-Oracle 索引的新建与重建

小伙们日常里有没有被业务和BOSS要求新建索引或是重建索引&#xff1f;他们都想着既快又稳&#xff0c;那么索引在在Oracle上如何实现、新建、重建。原则是什么&#xff1a; 1、新建索引&#xff0c;查询是否高频且慢&#xff0c;索引列是否高选择性&#xff0c;新增索引对写负…

使用 Rust Clippy 的详细方案

使用 Rust Clippy 的详细方案 Rust Clippy 是一个强大的静态分析工具&#xff0c;帮助开发者识别代码中的潜在问题并改善代码质量。以下是如何充分利用 Clippy 的方法&#xff1a; 安装 Clippy 确保 Rust 工具链已安装。通过以下命令安装 Clippy&#xff1a; rustup compon…

21.什么是JSBridge(1)

1.Native与H5交互的常用交互机制&#xff0c;主流选择是jsbridge 2.jsbridge是什么&#xff1f; JSBridge 是 Android 官方 WebView 提供的 addJavascriptInterface() 能力 项目方&#xff08;或三方库&#xff09;封装的桥梁通信协议。 底层机制由 Android 官方 WebView 提…

什么是Flink

Apache Flink&#xff1a;流批一体的大数据处理引擎 什么是Apache Flink&#xff1f; Apache Flink是一个开源的分布式流处理框架&#xff0c;最初由柏林工业大学开发&#xff0c;后成为Apache软件基金会的顶级项目。它能够以高吞吐、低延迟的方式处理无界数据流(流处理)和有…

区块链+智能合约如何解决上门按摩行业的信任问题?——App开发案例

你是不是觉得上门按摩市场已经人满为患&#xff1f;担心自己入局太晚或者缺乏行业经验&#xff1f;一组真实数据可能会让你改变看法&#xff1a;全国按摩服务需求正以月均8%的速度迅猛增长&#xff0c;但专业技师的供给量仅能跟上5%的增幅&#xff01;这意味着每个月都有相当于…

修改windows hosts文件的软件

修改hosts文件的软件推荐及使用教程 这个软件我用了10多年 推荐工具&#xff1a;Hosts Host软件不用安装绿色 如何使用 注意事项 如何没有安装.net 3.5 请根据提示安装就可以了 内容绑定了软件下载资源&#xff0c;在顶部有需要的自己取

Java web非Maven项目中引入EasyExcel踩坑记录

最近在帮朋友在老项目上做二次开发&#xff0c;有读取Excel的需求&#xff0c;习惯性的引入了EasyExcel&#xff0c;但是出现了很多问题&#xff0c;最主要就是jar包的问题,需要依赖的jar包版本问题 项目技术栈&#xff1a; tomcat9 Amazon Corretto JDK 8 (亚马逊的openJDK…

Flutter——数据库Drift开发详细教程(七)

目录 入门设置 漂移文件入门变量数组定义表支持的列类型漂移特有的功能 导入嵌套结果LIST子查询Dart 互操作SQL 中的 Dart 组件类型转换器现有的行类Dart 文档注释 结果类名称支持的语句 入门 Drift 提供了一个dart_api来定义表和编写 SQL 查询。尤其当您已经熟悉 SQL 时&#…

【排坑指南】MySQL初始化后,Nacos与微服务无法连接??

Date&#xff1a;2025/06/18 你好&#xff01; 今天&#xff0c;分享一个工作中遇到的一个 MySQL 问题。在这之前都不知道是 MySQL 的问题&#xff0c;特离谱&#xff01; 昨天和今天大多数时间都用来处理了这一个问题&#xff1a;《MySQL进行了数据库初始化之后&#xff0c…

springboot获取工程目录

在springboot中使用ApplicationHome获取工程所在目录的时候&#xff0c;开发环境和生产运行环境输出的目录是不同的&#xff0c;开发环境到target/classes目录&#xff0c;而生产运行则是需要的wzkj-server.jar所在目录 ApplicationHome home new ApplicationHome(CollectTas…

深入ZGC并发处理的原理

大型Java应用的核心痛点之一&#xff1a;当JVM进行垃圾回收时强制程序暂停&#xff08;STW&#xff09;的代价。在要求低延迟的应用场景——高频交易系统、实时在线服务或全球性大型平台——中&#xff0c;这种"时空静止"的成本可能极高。但JDK从16版本&#xff08;生…