抛弃GdCpp*.dll/pdb历史重新建库。libhv和Sqlite的dll保留
This commit is contained in:
249
include/json/CJsonFile.h
Normal file
249
include/json/CJsonFile.h
Normal file
@@ -0,0 +1,249 @@
|
||||
#ifndef CJSONFILE_H
|
||||
#define CJSONFILE_H
|
||||
|
||||
#include "_nlohmann_json_wrapper.h"
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <filesystem>
|
||||
#include <atlstr.h>
|
||||
namespace fs = std::filesystem;
|
||||
/** @addtogroup ksjson
|
||||
* @{
|
||||
* @addtogroup files
|
||||
* @brief json/bson file classes.
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief The CJsonFile class
|
||||
*/
|
||||
class CJsonFile // header only class
|
||||
{
|
||||
public:
|
||||
|
||||
CJsonFile()
|
||||
:needSave(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// \brief 构造函数
|
||||
/// \param filepath 指定文件绝对路径,只保存了文件名,并没有打开文件。
|
||||
/// 如果未设置,后续必须通过setFilePath()指定文件的绝对路径
|
||||
template<typename T>
|
||||
CJsonFile(T filepath)
|
||||
{
|
||||
setFilePath(filepath);
|
||||
}
|
||||
|
||||
/// 设置文件路径
|
||||
/// \param path 文件的绝对路径
|
||||
|
||||
void setFilePath(const char* path) { _filePath = path; }
|
||||
void setFilePath(const wchar_t* path) { _filePath = path; }
|
||||
void setFilePath(const fs::path& path) { _filePath = path; }
|
||||
#ifdef UNICODE
|
||||
void setFilePath(const CString& path) { _filePath = (const wchar_t*)path; }
|
||||
#endif
|
||||
|
||||
// 判断是否设置了路径,没有判断路径是否有效
|
||||
bool hasFilePath() const { return !_filePath.empty(); }
|
||||
|
||||
bool exists() const { return !_filePath.empty() && fs::exists(_filePath); }
|
||||
|
||||
virtual ~CJsonFile() = default;
|
||||
|
||||
protected:
|
||||
/// 参数文件完整路径。可以在构造函数里指定,或用setPath()指定
|
||||
fs::path _filePath;
|
||||
|
||||
public:
|
||||
/// 文件内容与内存变量之间中转的json格式cache。
|
||||
jsonobj cache;
|
||||
|
||||
/// 标记参数是否需要保存。
|
||||
int needSave = 0;
|
||||
|
||||
// 错误字符串
|
||||
std::string errStr;
|
||||
|
||||
/// 清空json缓存
|
||||
void clearCache() { cache = jsonobj(); }
|
||||
|
||||
/// 获取文件路径
|
||||
const fs::path& filePath() const { return _filePath; }
|
||||
|
||||
void reset() {
|
||||
cache.clear();
|
||||
_filePath.clear();
|
||||
}
|
||||
|
||||
enum {
|
||||
jFileNotExist=0,
|
||||
jFileOk =1,
|
||||
jFileFailOpenRead=-1,
|
||||
jFileFailOpenWrite=-2,
|
||||
jFileParseError=-3,
|
||||
jFileNull=-4,
|
||||
jFileOutputError=-5,
|
||||
jfileJsonToStructError=-6,
|
||||
jfileJsonFromStructError = -7,
|
||||
};
|
||||
|
||||
// ----保存和加载的函数相关 -----
|
||||
/// 从文件加载json/bson到cache,加载后关闭文件。
|
||||
/// 需要在构造函数中或用setFilePath()设置文件的完整路径
|
||||
/// \return 1: 文件打开ok,解析json正确;0:文件打开失败;-1:文件打开成功,解析json出错
|
||||
virtual int load()
|
||||
{
|
||||
// 调用处必须保证已经设置了路径
|
||||
_ASSERT(!_filePath.empty());
|
||||
|
||||
if (!fs::exists(_filePath)) {
|
||||
errStr = fmt::format("json文件不存在:{}", _filePath.string());
|
||||
return jFileNotExist;
|
||||
}
|
||||
|
||||
std::ifstream in(_filePath);
|
||||
if (in.is_open()) {
|
||||
try {
|
||||
in >> cache;
|
||||
needSave = 0;
|
||||
in.close();
|
||||
return jFileOk;
|
||||
}
|
||||
catch (jsonobj::exception& e) {
|
||||
//throw parse_error.101 in case of an unexpected token
|
||||
//throw parse_error.102 if to_unicode fails or surrogate error
|
||||
//throw parse_error.103 if to_unicode fails
|
||||
errStr = fmt::format("解析json出错:{}\n{}", _filePath.string(), e.what());
|
||||
in.close();
|
||||
return jFileParseError;
|
||||
}
|
||||
}
|
||||
else {
|
||||
errStr = fmt::format("json文件只读打开失败:{}", _filePath.string());
|
||||
return jFileFailOpenRead;
|
||||
}
|
||||
}
|
||||
|
||||
/// 保存cache到指定的文件,覆盖文件内容,写完后关闭文件,但内存中保存json格式的cache。
|
||||
/// 需要在构造函数中或用setFilePath()设置文件的完整路径。
|
||||
/// \return 1: 文件保存成功;0: 文件创建失败;-1: json中有字符串不是utf-8
|
||||
virtual int save()
|
||||
{
|
||||
// 调用处必须保证已经设置了路径
|
||||
_ASSERT(!_filePath.empty());
|
||||
|
||||
std::ofstream o(_filePath, std::ofstream::trunc);
|
||||
if (o.is_open()) {
|
||||
try {
|
||||
o << std::setw(4) << cache << std::endl;
|
||||
o.flush();
|
||||
needSave = 0;
|
||||
return jFileOk;
|
||||
}
|
||||
catch (jsonobj::exception& e) {
|
||||
// throw type_error.316 if a string stored inside the JSON value is not UTF-8 encoded
|
||||
errStr = fmt::format("转换json文本出错:{}\n{}", _filePath.string(), e.what());
|
||||
return jFileOutputError;
|
||||
}
|
||||
}
|
||||
else {
|
||||
errStr = fmt::format("json文件写入打开失败:{}", _filePath.string());
|
||||
return jFileFailOpenWrite;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int save(const T& src, bool clearBeforeSave=false) {
|
||||
if (clearBeforeSave) clearCache();
|
||||
try {
|
||||
to_json(cache, src);
|
||||
}
|
||||
catch (jsonobj::exception& e) {
|
||||
errStr = fmt::format("json<= 结构体出错:{}\n{}", _filePath.string(), e.what());
|
||||
return jfileJsonFromStructError;
|
||||
}
|
||||
|
||||
return save();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int load(T& dst) {
|
||||
|
||||
errStr.clear();
|
||||
int ret = jFileOk;
|
||||
do {
|
||||
ret = load();
|
||||
if (ret != 1) break;
|
||||
if (cache.is_null()) {
|
||||
errStr = fmt::format("读到的json是空的:{}", _filePath.string());
|
||||
ret = jFileNull;
|
||||
break;
|
||||
}
|
||||
try {
|
||||
from_json(cache, dst);
|
||||
}
|
||||
catch (jsonobj::exception& e) {
|
||||
errStr = fmt::format("json => 结构体出错:{}\n{}", _filePath.string(), e.what());
|
||||
ret = jfileJsonToStructError;
|
||||
break;
|
||||
}
|
||||
return jFileOk;
|
||||
} while (0);
|
||||
alog->error(errStr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// 将cache中名为name的部分转到结构体T的实例dst
|
||||
template <typename T>
|
||||
int copyToStruct(const char* name, T& dst)
|
||||
{
|
||||
if (cache.contains(name)) {
|
||||
try {
|
||||
cache[name].get_to<T>(dst);
|
||||
}
|
||||
catch (jsonobj::exception& e) {
|
||||
errStr = fmt::format("json {} => 结构体出错:{}\n{}", name, _filePath.string(), e.what());
|
||||
return jfileJsonToStructError;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// 将结构体T的实例src内容转成json保存到cache中名为name的字段
|
||||
template <typename T>
|
||||
void saveToCache(const char* name, const T& src)
|
||||
{
|
||||
try {
|
||||
cache[name] = src;
|
||||
}
|
||||
catch (jsonobj::exception& e) {
|
||||
errStr = fmt::format("json {} <= 结构体出错:{}\n{}", name, _filePath.string(), e.what());
|
||||
return jfileJsonFromStructError;
|
||||
}
|
||||
needSave++;
|
||||
}
|
||||
};
|
||||
|
||||
class CBsonFile : public CJsonFile
|
||||
{
|
||||
public:
|
||||
/// 重载load函数,将json改成bson。
|
||||
virtual int load()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// 重载load函数,将json改成bson。
|
||||
virtual int save()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
/** @} files */
|
||||
/** @} ksjson */
|
||||
#endif // CJSONFILE_H
|
||||
120
include/json/ParaHelper.h
Normal file
120
include/json/ParaHelper.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#ifndef PARAHELPER_H
|
||||
#define PARAHELPER_H
|
||||
|
||||
/**
|
||||
* \file ParaHelper.h
|
||||
*
|
||||
* \brief 定义一些帮助设置参数用的结构体,如\ref sParaRange
|
||||
*
|
||||
**/
|
||||
|
||||
#include "_nlohmann_json_wrapper.h"
|
||||
#include "StringHelper.h"
|
||||
#include "ParaHelper_core.h"
|
||||
|
||||
/** @addtogroup ksjson
|
||||
* @{
|
||||
* @addtogroup ParaHelper
|
||||
* @brief 定义sParaRange结构体,用于设置参数的缺省值、最小值、最大值,已经步进值,小数位数等属性。
|
||||
* @{ */
|
||||
|
||||
#ifndef ConstExpr
|
||||
/// 需要在一个类/结构体内部定义静态常量表达示时,
|
||||
/// 将"static constexpr auto"简写为ConstExpr
|
||||
#define ConstExpr static constexpr const auto
|
||||
#endif
|
||||
|
||||
/// 给变量添加注释的宏。
|
||||
/// var是变量
|
||||
/// str1、str2是变量含义和详细描述。
|
||||
/// 只支持const wchar_t*类型的字符串,方便在UI显示。
|
||||
#define ParaComment(var, str1, str2) \
|
||||
ConstExpr var##_title = str1; \
|
||||
ConstExpr var##_descr = str2;
|
||||
|
||||
static inline std::string combine_strs(const wchar_t* s1, const wchar_t* s2)
|
||||
{
|
||||
if (wcslen(s2))
|
||||
return utf16_8(std::wstring(s1) + L": " + s2);
|
||||
else
|
||||
return utf16_8(s1);
|
||||
}
|
||||
|
||||
// 变量转json并附加注释,适用于可以直接转json的变量
|
||||
#define TO_JSON_COMMENT(j, name, var) \
|
||||
j[#name##"?"] = combine_strs(var##_title, var##_descr); \
|
||||
j[#name] = var;
|
||||
|
||||
// wstring型变量转json并附加注释
|
||||
#define TO_JSON_COMMENT_WSTR(j, name, var) \
|
||||
j[#name##"?"] = combine_strs(var##_title, var##_descr); \
|
||||
j[#name] = utf16_8(var);
|
||||
|
||||
// wstring型vector变量转json并附加注释
|
||||
#define TO_JSON_COMMENT_WSTRVECTOR(j, name, var) {\
|
||||
j[#name##"?"] = combine_strs(var##_title, var##_descr); \
|
||||
jsonobj jarr=jsonobj::array(); \
|
||||
for(auto& s : var) jarr.push_back(utf16_8(s)); \
|
||||
j[#name] = jarr; \
|
||||
}
|
||||
|
||||
// 类转json并附加注释,适合自定义了to_json()函数的类或结构体
|
||||
#define TO_JSON_COMMENT_CLASS(j, name, var) \
|
||||
j[#name##"?"] = combine_strs(var##_title, var##_descr); \
|
||||
to_json(j[#name], var);
|
||||
|
||||
/// sParaRange -> json
|
||||
template <typename T>
|
||||
void to_json(jsonobj& j, const sParaRange<T> & p) {
|
||||
j["def"] = p.Def;
|
||||
j["min"] = p.Min;
|
||||
j["max"] = p.Max;
|
||||
j["step"] = p.Step;
|
||||
if(typeid (T) == typeid (float) || typeid (T) == typeid (double)){
|
||||
//浮点型才保存Decimal
|
||||
j["decimal"] = p.Decimal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// json -> sParaRange
|
||||
/// 手写的json文件有两种格式:
|
||||
/// 一种每一项用key:value单独设置,必须存在def,min,max;
|
||||
/// 一种写成数组,必须存在3项。
|
||||
/// 程序写的json见to_json()
|
||||
template <typename T>
|
||||
void from_json(const jsonobj& j, sParaRange<T>& p) {
|
||||
if(!j.is_array()){ //key:value方式单独设置各项
|
||||
//注意:def, min, max 必须存在,要不然这会抛异常的!
|
||||
j["def" ].get_to<T>(p.Def);
|
||||
j["min" ].get_to<T>(p.Min);
|
||||
j["max" ].get_to<T>(p.Max);
|
||||
|
||||
// 判断step是否存在再读
|
||||
auto it = j.find("step");
|
||||
if(it!=j.end()) it->get_to<T>(p.Step);
|
||||
|
||||
// 判断decimal是否存在再读
|
||||
it = j.find("decimal");
|
||||
if(it!=j.end()) it->get_to<int>(p.Decimal);
|
||||
}else{
|
||||
//至少要有三项。TODO: 如何报错?
|
||||
int size = int(j.size());
|
||||
if(size<3) return;
|
||||
j[0].get_to<T>(p.Def);
|
||||
j[1].get_to<T>(p.Min);
|
||||
j[2].get_to<T>(p.Max);
|
||||
|
||||
//有4项则读step
|
||||
if(size >= 4) j[3].get_to<T>(p.Step);
|
||||
|
||||
//有5项则读decimal
|
||||
if(size >= 5) p.Decimal = int(j[4].get<T>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @} ParaHelper */
|
||||
/** @} ksjson */
|
||||
|
||||
#endif // PARAHELPER_H
|
||||
70
include/json/ParaHelper_core.h
Normal file
70
include/json/ParaHelper_core.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef _PARAHELPER_CORE_H
|
||||
#define _PARAHELPER_CORE_H
|
||||
|
||||
/// \brief 定义整形、浮点型参数的缺省值和取值范围,类型T可以为8/16/32/64位的有符号或无符号数、float/double。
|
||||
template <typename T>
|
||||
struct sParaRange
|
||||
{
|
||||
/// 默认构造后不能直接使用,必须正确设置Def/Min/Max参数才能使用
|
||||
sParaRange() = default;
|
||||
|
||||
/// 带所有参数测构造函数。当所有参数都是常数或constexpr时,构造的实例可以是constexpr
|
||||
constexpr sParaRange(const T &def, const T & min, const T & max, const T& step=1, int dec=2)
|
||||
: Def(def), Min(min), Max(max), Step(step)
|
||||
, Decimal(dec)
|
||||
{
|
||||
}
|
||||
|
||||
/// 必须设的参数:缺省值, 最小值, 最大值。默认构造为0是没法使用的
|
||||
T Def=0, Min=0, Max=0;
|
||||
|
||||
/// 可选设置的参数:在UI控件中调整参数的步进值,默认为1
|
||||
T Step=1;
|
||||
|
||||
/// 小数位数,仅用于float/double浮点型数据,整形数据忽略此项
|
||||
int Decimal=2;
|
||||
|
||||
/// 判断输入参数是否在[Min, Max]范围内
|
||||
bool inRange(const T & val) const {
|
||||
return (val>=Min && val <= Max);
|
||||
}
|
||||
|
||||
/// @brief 校验参数,如果小于Min设置为Min,大于Max设置为Max
|
||||
bool verify(T& val) const {
|
||||
if (val < Min) { val = Min; return false; }
|
||||
else if (val > Max) { val = Max; return false; }
|
||||
else return true;
|
||||
}
|
||||
|
||||
/// @brief 校验参数,如果小于Min设置为Min,大于Max设置为Max
|
||||
/// @param err 误差值,多用于浮点数比较
|
||||
bool verify(T& val, const T err) const {
|
||||
if (val < Min-err) { val = Min; return false; }
|
||||
else if (val > Max+err) { val = Max; return false; }
|
||||
else return true;
|
||||
}
|
||||
|
||||
/// @brief 校验参数,如果超出范围,设置为缺省值
|
||||
bool verifyToDefault(T& val) const{
|
||||
if (val <Min || val > Max) { val = Def; return false;}
|
||||
else return true;
|
||||
}
|
||||
|
||||
/// @brief 校验参数,如果超出范围,设置为缺省值
|
||||
bool verifyToDefault(T& val, const T err) const {
|
||||
if (val <Min-err || val > Max+err) { val = Def; return false; }
|
||||
else return true;
|
||||
}
|
||||
|
||||
sParaRange operator+(T d) const
|
||||
{
|
||||
return sParaRange(Def + d, Min + d, Max + d, Step, Decimal);
|
||||
}
|
||||
|
||||
sParaRange operator-(T d) const
|
||||
{
|
||||
return sParaRange(Def - d, Min - d, Max - d, Step, Decimal);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
41
include/json/_nlohmann_json_wrapper.h
Normal file
41
include/json/_nlohmann_json_wrapper.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef NLOHMANN_JSON_WRAPPER_H
|
||||
#define NLOHMANN_JSON_WRAPPER_H
|
||||
|
||||
#include "json.hpp"
|
||||
#include "GdCPP_Exports.h"
|
||||
/**
|
||||
* @addtogroup ksjson
|
||||
* @{
|
||||
* @addtogroup nlohmann_json_wrapper
|
||||
* @brief 引用nlohmann::json的类和异常等。
|
||||
* @details
|
||||
* @{
|
||||
*/
|
||||
|
||||
/// \brief 将nlohmann::json定义为jsonobj,简化掉namespace的访问。
|
||||
///
|
||||
/// 本来想用json,但语义不够明确。因此采用了一个跟Qt的QJsonObject近似的名称,
|
||||
/// 表示可以替代QJsonObject,实际上这个类的功能很强大,可以完全替代QJsonObject、QJsonValue、QJsonArray,
|
||||
/// 可以替代QJsonDocument的部分功能,甚至也能部分替代QVariant用。
|
||||
using jsonobj = nlohmann::ordered_json;
|
||||
|
||||
// 以下定义用于简化json的异常类型的访问
|
||||
using json_exception = nlohmann::json::exception;
|
||||
using json_parse_err = nlohmann::json::parse_error;
|
||||
using json_invalid_iterator = nlohmann::json::invalid_iterator;
|
||||
using json_type_error = nlohmann::json::type_error;
|
||||
using json_out_of_range = nlohmann::json::out_of_range;
|
||||
using json_other_error = nlohmann::json::other_error;
|
||||
|
||||
// 判断数据类型是否可以做json的key
|
||||
template <typename T> struct JsonKey;
|
||||
template <> struct JsonKey<const std::string&> { typedef const std::string& Type; };
|
||||
template <> struct JsonKey<const char * > { typedef const char* Type; };
|
||||
|
||||
// 判断类型是否可以做数组长度
|
||||
template <typename T> struct ArraySizeT;
|
||||
template <> struct ArraySizeT<int> { typedef int Type; };
|
||||
template <> struct ArraySizeT<size_t> { typedef size_t Type; };
|
||||
/** @} nlohmann_json_wrapper */
|
||||
/** @} ksjson */
|
||||
#endif // NLOHMANN_JSON_WRAPPER_H
|
||||
16
include/json/jsonCVWrapper.h
Normal file
16
include/json/jsonCVWrapper.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
// opencv不是所有项目都包含,按需要添加到pch.h
|
||||
// 对应jsonCVWrapper.cpp源码添加到项目
|
||||
|
||||
#ifndef _JSON_OPENCV_WRAPPER_
|
||||
#define _JSON_OPENCV_WRAPPER_
|
||||
|
||||
void to_json(jsonobj& j, const cv::Point& p);
|
||||
void from_json(const jsonobj& j, cv::Point& p);
|
||||
void to_json(jsonobj& j, const cv::Point2f& p);
|
||||
void from_json(const jsonobj& j, cv::Point2f& p);
|
||||
void to_json(jsonobj& j, const cv::Size& p);
|
||||
void from_json(const jsonobj& j, cv::Size& p);
|
||||
void to_json(jsonobj& j, const cv::Rect& p);
|
||||
void from_json(const jsonobj& j, cv::Rect& p);
|
||||
#endif //_JSON_OPENCV_WRAPPER_
|
||||
421
include/json/jsonReadWithVerify.h
Normal file
421
include/json/jsonReadWithVerify.h
Normal file
@@ -0,0 +1,421 @@
|
||||
#ifndef JSONREADWITHVERIFY_H
|
||||
#define JSONREADWITHVERIFY_H
|
||||
|
||||
#include "_nlohmann_json_wrapper.h"
|
||||
#include "ParaHelper.h"
|
||||
#include "alog.h"
|
||||
|
||||
/** @addtogroup ksjson
|
||||
* @{
|
||||
* @addtogroup readWithVerify
|
||||
* @brief 从json转换到数值前判断key是否存在,确认数值是否在一定[min, max]范围内,或在一个数组列表范围之内。
|
||||
* @{
|
||||
*/
|
||||
|
||||
/// \brief 尝试从obj读取键值为key的数据,没找到不赋值返回false,找到就给指针赋值并返回true。
|
||||
/// \details 通常用于已经初始化为默认值的变量或结构体,找到就读,没找到就保持默认值。
|
||||
/// 注意保存的格式要跟写入的格式一致,别写个string当int读,肯定会出问题的。这里就没法检验格式是否正确了。
|
||||
///
|
||||
/// \param obj nlohmann::json对象
|
||||
/// \param key 键值,类型KeyT支持类型const char *, std::string
|
||||
/// \param dst 目标变量,类型ValueT可以是所有支持的数据类型,包括nlohmann::json标准的数据类型和定义了to_json和from_json的类型。
|
||||
/// \return 没找到返回0,找到返回1。
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int tryRead(const jsonobj& obj, KeyT key, ValueT& dst)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) return 0; //没找到
|
||||
it->template get_to<ValueT>(dst);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// 尝试从obj读取键值为key的数据,没找到设置为缺省值并返回false,找到就读取数值给指针赋值并返回true。
|
||||
/// 类型ValueT可以是所有支持的数据类型,包括nlohmann::json标准的数据类型和定义了to_json和from_json的类型。
|
||||
/// \param obj nlohmann::json对象
|
||||
/// \param dst 目标变量。
|
||||
/// \param key 键值,类型KeyT支持类型const char *, std::string
|
||||
/// \param def 找不到键值使用的缺省值。def的数据类型ValueT2必须与dst的数据类型ValueT可以直接隐式转换或复制构造的
|
||||
/// \return 没找到返回false,找到返回true。
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT, typename ValueT2>
|
||||
int readWithDefault(const jsonobj& obj, KeyT key, ValueT& dst, ValueT2 def)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) {//没找到
|
||||
dst = def;
|
||||
return 0;
|
||||
}
|
||||
it->template get_to<ValueT>(dst);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// \brief 在\ref readWithDefault 基础上增加了校验读到的值是否在[min, max]范围之内。
|
||||
/// \details 类型ValueT通常是数值类型。其它支持的数据类型如果它支持用大于号/小于号比较的类型也行,估计很少会用到。
|
||||
/// \param obj nlohmann::json对象
|
||||
/// \param key 键值,类型KeyT支持类型const char *, std::string
|
||||
/// \param dst 目标变量。
|
||||
/// \param def 找不到键值使用的缺省值。def的数据类型必须与dst的数据类型可以直接转换的
|
||||
/// \param min 取值范围的下限,min << value << max
|
||||
/// \param max 取值范围的上限,min << value << max
|
||||
/// \return 返回读取状态。
|
||||
/// 没找到返回0,找到但数值超界返回-1,找到并在有效范围内返回1。
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT, typename ValueT2, typename ValueT3>
|
||||
int readInRange(const jsonobj& obj, KeyT key, ValueT& dst, const ValueT2& def, const ValueT3& min, const ValueT3& max)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) {//没找到
|
||||
dst = ValueT(def);
|
||||
return 0;
|
||||
}
|
||||
ValueT tmp = it->template get<ValueT>();
|
||||
if (tmp < ValueT(min)) {
|
||||
dst = ValueT(min);
|
||||
return -1;
|
||||
}
|
||||
else if (tmp > ValueT(max)) {//超界
|
||||
dst = ValueT(max);
|
||||
return -1;
|
||||
}
|
||||
// 返回读取值
|
||||
dst = tmp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// \brief 重载\ref readInRange 用sParaRange<ValueT>做取值范围的校验。
|
||||
/// \details 用sParaRange的成员变量Def, Min, Max替代\ref readInRange的def, min, max参数
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
inline int readInRange(const jsonobj& obj, KeyT key, ValueT& dst, const sParaRange<ValueT>& range)
|
||||
{
|
||||
return readInRange(obj, key, dst, range.Def, range.Min, range.Max);
|
||||
}
|
||||
|
||||
/// \brief json --> ValueT,并校验数值是否在数组list[num]范围类
|
||||
/// \details
|
||||
/// - 没找到:返回值为0,dst设置为def<br>
|
||||
/// - 找到但数值布置在列表范围内:返回值-1,dst设置为def<br>
|
||||
/// - 找到并在列表范围内:返回1,dst设置为解析值。<br>
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT, typename NumT, typename = ArraySizeT<NumT>::Type>
|
||||
int readInList(const jsonobj& obj, KeyT key, ValueT& dst, const ValueT& def, const ValueT* list, NumT num)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) {//没找到
|
||||
dst = def;
|
||||
return 0;
|
||||
}
|
||||
ValueT tmp = it->template get<ValueT>();
|
||||
for (int i = 0; i < num; i++) { //不在列表中
|
||||
if (tmp == list[i]) {
|
||||
dst = tmp;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
dst = def;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// \brief json --> ValueT,并校验数值是否在QVector<ValueT>列表范围类
|
||||
/// \details
|
||||
/// - 没找到:返回值为0,dst设置为def<br>
|
||||
/// - 找到但数值布置在列表范围内:返回值-1,dst设置为def<br>
|
||||
/// - 找到并在列表范围内:返回1,dst设置为解析值。<br>
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readInList(const jsonobj& obj, KeyT key, ValueT& dst, const ValueT& def, std::vector<ValueT> list)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) {//没找到
|
||||
dst = def;
|
||||
return 0;
|
||||
}
|
||||
ValueT tmp = it->template get<ValueT>();
|
||||
if (list.contains(tmp)) {
|
||||
dst = tmp;
|
||||
return 1;
|
||||
}
|
||||
dst = def;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// \brief json --> ValueT,并校验数值是否在QList<ValueT>列表范围类
|
||||
/// \details
|
||||
/// - 没找到:返回值为0,dst设置为def<br>
|
||||
/// - 找到但数值布置在列表范围内:返回值-1,dst设置为def<br>
|
||||
/// - 找到并在列表范围内:返回1,dst设置为解析值。<br>
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readInList(const jsonobj& obj, KeyT key, ValueT& dst, const ValueT& def, std::list<ValueT> list)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) {//没找到
|
||||
dst = def;
|
||||
return 0;
|
||||
}
|
||||
ValueT tmp = it->template get<ValueT>();
|
||||
if (list.contains(tmp)) {
|
||||
dst = tmp;
|
||||
return 1;
|
||||
}
|
||||
dst = def;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// \brief 从json读入string, 与strlist里的字符串比较,确定枚举值。
|
||||
/// \details
|
||||
/// \param strlist 字符串列表
|
||||
/// \param num 字符串个数
|
||||
/// \param vallist 枚举值列表。<br>
|
||||
/// vallist可以为null,代表枚举值如果是从0开始顺序递增的,dst设置为strlist数组的下标。<br>
|
||||
/// \return <br>
|
||||
/// - 没找到:返回值为0,dst设置为def<br>
|
||||
/// - 找到但字符串不在列表范围内:返回值-1,dst设置为def<br>
|
||||
/// - 找到并在列表范围内:返回1。如果vallist为null,dst设置strlist数组的下表;如果vallist非空,dst设置为对于的数组。<br>
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readEnum(const jsonobj& obj, KeyT key, ValueT& dst, int def, const char* const* strlist, int num, const int* vallist = nullptr)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) {//没找到
|
||||
alog->warn("readEnum 没找到{},返回缺省值", key);
|
||||
dst = ValueT(def);
|
||||
return 0;
|
||||
}
|
||||
if (it->is_string()) {
|
||||
std::string str = it->template get<std::string>();
|
||||
for (int i = 0; i < num; i++) {
|
||||
if (str.compare(strlist[i]) == 0) {
|
||||
if (vallist) dst = ValueT(vallist[i]);
|
||||
else dst = ValueT(i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
alog->warn("readEnum {}没有匹配到字符串{},返回缺省值", key);
|
||||
dst = ValueT(def);
|
||||
}
|
||||
else if (it->is_number_integer()) {
|
||||
int val = it->template get<int>();
|
||||
if (vallist) {
|
||||
for (int i = 0; i < num; i++) {
|
||||
if (val == vallist[i]) {
|
||||
dst = ValueT(val);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
alog->warn("readEnum {}数值不在列表中,返回缺省值", key);
|
||||
dst = ValueT(def);
|
||||
}
|
||||
else {
|
||||
if (val >= 0 && val < num) {
|
||||
dst = ValueT(val);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
alog->warn("readEnum {}数值超界,返回缺省值", key);
|
||||
dst = ValueT(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
alog->error("{}的json类型错误,应该是字符串或整形,未修改结果", key);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 与上一版本的区别是没有缺省值
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readEnum(const jsonobj& obj, KeyT key, ValueT& dst, const char* const * strlist, int num, const int* vallist = nullptr)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) {//没找到
|
||||
alog->warn("readEnum 没找到{},返回缺省值", key);
|
||||
return 0;
|
||||
}
|
||||
if (it->is_string()) {
|
||||
std::string str = it->template get<std::string>();
|
||||
for (int i = 0; i < num; i++) {
|
||||
if (str.compare(strlist[i]) == 0) {
|
||||
if (vallist) dst = ValueT(vallist[i]);
|
||||
else dst = ValueT(i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
alog->warn("readEnum {}没有匹配到字符串{},未赋值", key);
|
||||
}
|
||||
else if (it->is_number_integer()) {
|
||||
int val = it->template get<int>();
|
||||
if (vallist) {
|
||||
for (int i = 0; i < num; i++) {
|
||||
if (val == vallist[i]) {
|
||||
dst = ValueT(val);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
alog->warn("readEnum {}数值不在列表中,未赋值", key);
|
||||
}
|
||||
else {
|
||||
if (val >= 0 && val < num) {
|
||||
dst = ValueT(val);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
alog->warn("readEnum {}数值超界,未赋值", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
alog->error("{}的json类型错误,应该是字符串或整形,未修改结果", key);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// \brief 从json读入string, 与strlist里的字符串比较,确定枚举值。
|
||||
/// \details
|
||||
/// \param strlist 字符串列表
|
||||
/// \param vallist 枚举值列表。<br>
|
||||
/// \return <br>
|
||||
/// - 没找到:返回值为0,dst设置为def<br>
|
||||
/// - 找到但字符串不在列表范围内:返回值-1,dst设置为def<br>
|
||||
/// - 找到并在列表范围内:返回1。如果vallist为null,dst设置strlist数组的下表;如果vallist非空,dst设置为对于的数组。<br>
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT, typename ValutT2>
|
||||
int readEnum(const jsonobj& obj, KeyT key, ValueT& dst, ValutT2 def, const char** strlist, const std::vector<ValueT>& vallist)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) {//没找到
|
||||
dst = ValueT(def);
|
||||
return 0;
|
||||
}
|
||||
std::string str = it->template get<std::string>();
|
||||
for (int i = 0; i < vallist.size(); i++) {
|
||||
if (str.compare(strlist[i]) == 0) {
|
||||
dst = vallist[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
dst = ValueT(def);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// 将C++枚举数组转换为字符串数组写入json
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
void writeEnumArray(jsonobj& obj, KeyT key, const char* const* strlist, int strnum, const std::vector<ValueT> &valuelist)
|
||||
{
|
||||
auto arr=jsonobj::array();
|
||||
for(auto &val : valuelist) {
|
||||
if (val < 0 || val >= strnum) {
|
||||
alog->error("writeEnum {}数值超界", key);
|
||||
return;
|
||||
}
|
||||
arr.push_back(strlist[val]);
|
||||
}
|
||||
obj[key] = arr;
|
||||
}
|
||||
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readEnumArray(const jsonobj& obj, KeyT key, std::vector<ValueT>& dst, const char* const* strlist, int num)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end()) {//没找到
|
||||
alog->warn("readEnumArray 没找到{}", key);
|
||||
return 0;
|
||||
}
|
||||
if (!it->is_array()) {
|
||||
alog->error("readEnumArray {} 不是数组", key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (it->size() == 0) {
|
||||
alog->error("readEnumArray {} 是空数组", key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dst.clear();
|
||||
for (auto& x : *it) {
|
||||
if (x.is_string()) {
|
||||
std::string str=x.get<std::string >();
|
||||
int i = 0;
|
||||
for (; i < num; i++) {
|
||||
if (str.compare(strlist[i]) == 0) {
|
||||
dst.push_back(ValueT(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i==num )alog->warn("readEnumArray {}没有匹配到字符串{},未赋值", key, str);
|
||||
}
|
||||
else {
|
||||
alog->error("{}的json类型错误,应该是字符串,未修改结果", key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return int(dst.size());
|
||||
}
|
||||
|
||||
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type>
|
||||
int readStr(const jsonobj& obj, const KeyT& key, char* dst, int dstsize)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) {//没找到,或空
|
||||
memset(dst, 0, dstsize);
|
||||
return 0;
|
||||
}
|
||||
if (!it->is_string()) { //不是字符串
|
||||
return -1;
|
||||
}
|
||||
std::string str = it->template get<std::string>();
|
||||
auto len = str.length();
|
||||
if (len >= dstsize) {
|
||||
return -2;
|
||||
}
|
||||
else if (len == 0) {
|
||||
*dst = 0;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
memcpy(dst, str.c_str(), len);
|
||||
*(dst + len) = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读入char型数值,如果长度刚好填满,不用0结束
|
||||
/// </summary>
|
||||
/// <typeparam name="KeyT"></typeparam>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="dst"></param>
|
||||
/// <param name="dstsize"></param>
|
||||
/// <returns></returns>
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type>
|
||||
int readCharArray(const jsonobj& obj, const KeyT& key, char* dst, int dstsize, char fill)
|
||||
{
|
||||
auto it = obj.find(key);
|
||||
if (it == obj.end() || it->is_null()) {//没找到,或空
|
||||
memset(dst, 0, dstsize);
|
||||
return 0;
|
||||
}
|
||||
if (!it->is_string()) { //不是字符串
|
||||
return -1;
|
||||
}
|
||||
std::string str = it->template get<std::string>();
|
||||
auto len = str.length();
|
||||
if (len > dstsize) {
|
||||
return -2;
|
||||
}
|
||||
else {
|
||||
memcpy(dst, str.c_str(), len);
|
||||
if (len < dstsize) {
|
||||
memset(dst + len, fill, dstsize - len);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** @} readWithCheck*/
|
||||
/** @} json*/
|
||||
|
||||
#endif // JSONREADWITHVERIFY_H
|
||||
573
include/json/jsonVCWrapper.h
Normal file
573
include/json/jsonVCWrapper.h
Normal file
@@ -0,0 +1,573 @@
|
||||
#ifndef JSON_VC_WRAPPER_H
|
||||
#define JSON_VC_WRAPPER_H
|
||||
|
||||
#include "_nlohmann_json_wrapper.h"
|
||||
#include <atlstr.h> // for CString
|
||||
#include <atltypes.h> // for CPoint, CSize, CRect
|
||||
|
||||
#include "StringHelper.h"
|
||||
|
||||
// wchar_t定义to_json没用,直接用j["keyname"] = utf16_8(wstr);
|
||||
// GDCPP_API void to_json(jsonobj& j, const wchar_t * p);
|
||||
|
||||
// wstring定义to_json没用,直接用j["keyname"] = utf16_8(wstr);
|
||||
// GDCPP_API void to_json(jsonobj& j, const std::wstring& p);
|
||||
|
||||
// std::wstring用from_josn会报错,用下面的toWstring
|
||||
//GDCPP_API void from_json(const jsonobj& j, std::wstring& p);
|
||||
bool toWstring(const jsonobj& j, std::wstring& dst);
|
||||
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type>
|
||||
int readWstring(const jsonobj& j, KeyT key, std::wstring& dst)
|
||||
{
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null()) {//没找到
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (it->is_string()) { // 判断是否为string类型的数据,避免get函数抛出异常
|
||||
dst = utf8_16(it->get<std::string>());
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type>
|
||||
int readWstringVector(const jsonobj& j, KeyT key, std::vector<std::wstring>& dst, bool clearbeforeread)
|
||||
{
|
||||
if (clearbeforeread) {
|
||||
dst.clear();
|
||||
}
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null()) {//没找到
|
||||
return 0;
|
||||
}
|
||||
if (!it->is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
std::string str;
|
||||
for (auto& i : *it) {
|
||||
str = i.get<std::string>();
|
||||
dst.push_back(utf8_16(str));
|
||||
}
|
||||
return int(it->size());
|
||||
}
|
||||
|
||||
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type>
|
||||
int readWstring(const jsonobj& j, KeyT key, std::wstring& dst, const std::wstring &def)
|
||||
{
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null()) {//没找到
|
||||
dst = def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (it->is_string()) { // 判断是否为string类型的数据,避免get函数抛出异常
|
||||
dst = utf8_16(it->get<std::string>());
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void to_json(jsonobj& j, const CString& p);
|
||||
void from_json(const jsonobj& j, CString& p);
|
||||
|
||||
void to_json(jsonobj& j, const CPoint& p);
|
||||
void from_json(const jsonobj& j, CPoint& p);
|
||||
|
||||
void to_json(jsonobj& j, const CSize& p);
|
||||
void from_json(const jsonobj& j, CSize& p);
|
||||
|
||||
void to_json(jsonobj& j, const CRect& p);
|
||||
void from_json(const jsonobj& j, CRect& p);
|
||||
|
||||
|
||||
/** @addtogroup Vector
|
||||
* @brief std::vector <---> jsonobj
|
||||
* @{*/
|
||||
/// \brief std::vector <T> -> json,T不要是指针类型,模板匹配有问题
|
||||
/// \details 注意会先清空j,如果j之前不是array也会强制变成array.
|
||||
template <typename T>
|
||||
void to_json(jsonobj& j, const std::vector <T>& p) {
|
||||
j = jsonobj::array(); //先清空
|
||||
int num = int(p.size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
j.push_back(p.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief json -> std::vector <T>,T不要是指针类型,模板匹配有问题
|
||||
/// \details 注意会先清空p!不想清空就用\ref readVector
|
||||
template <typename T>
|
||||
void from_json(const jsonobj& j, std::vector <T>& p) {
|
||||
p.clear(); //先清空
|
||||
if (j.is_array()) {
|
||||
size_t num = j.size();
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
p.push_back(j.at(i).get<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief json --> std::vector<ValueT>,不会清除原有数据。注意没有判断json里的数据是否与ValueT类型匹配,需要应用层保证
|
||||
///
|
||||
/// \param j nlohmann::json对象
|
||||
/// \param key 键值,类型KeyT支持类型const char *, std::string
|
||||
/// \param dst 目标变量。
|
||||
/// \return 没找到返回0,找到但不是数组类型-1,有数据返回读到的数据类型。
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename = JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readVector(const jsonobj& j, KeyT key, std::vector<ValueT>& dst)
|
||||
{
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null()) {//没找到
|
||||
return 0;
|
||||
}
|
||||
if (!it->is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
int num = int(it->size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
// 基础类不能用from_json,只能用get_to
|
||||
dst.push_back(it->at(i).template get<ValueT>());
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename = JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readVector2D(const jsonobj& j, std::vector< std::vector<ValueT>>& dst)
|
||||
{
|
||||
if (!j.is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
int num = int(j.size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
std::vector<ValueT> sub;
|
||||
readVector(j.at(i), sub);
|
||||
dst.push_back(sub);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename = JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readVector2D(const jsonobj& j, KeyT key, std::vector< std::vector<ValueT>>& dst)
|
||||
{
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null()) {//没找到
|
||||
return 0;
|
||||
}
|
||||
if (!it->is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
int num = int(it->size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
std::vector<ValueT> sub;
|
||||
readVector(it->at(i), sub);
|
||||
dst.push_back(sub);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// \brief json --> std::vector<ValueT>,不会清除原有数据。注意没有判断json里的数据是否与ValueT类型匹配,需要应用层保证
|
||||
///
|
||||
/// \param j nlohmann::json对象
|
||||
/// \param dst 目标变量。
|
||||
/// \return 没找到返回0,找到但不是数组类型-1,有数据返回读到的数据类型。
|
||||
template <typename ValueT>
|
||||
int readVector(const jsonobj& j, std::vector<ValueT>& dst)
|
||||
{
|
||||
if (!j.is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
int num = int(j.size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
ValueT tmp;
|
||||
j.at(i).template get_to<ValueT>(tmp);
|
||||
dst.push_back(tmp);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/// \brief json --> std::vector<ValueT*>,不会清除原有数据。注意没有判断json里的数据是否与ValueT类型匹配,需要应用层保证
|
||||
///
|
||||
/// \param j nlohmann::json对象
|
||||
/// \param key 键值,类型KeyT支持类型const char *, std::string
|
||||
/// \param dst 目标变量。
|
||||
/// \return 没找到返回0,找到但不是数组类型-1,有数据返回读到的数据类型。
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readPtrVector(const jsonobj& j, KeyT key, std::vector<ValueT*>& dst)
|
||||
{
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null()) {//没找到
|
||||
return 0;
|
||||
}
|
||||
if (!it->is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
int num = int(it->size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
auto* item = new ValueT();
|
||||
it->at(i).template get_to<ValueT>(*item);
|
||||
dst.push_back(item);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/// \brief json --> std::vector<ValueT*>,不会清除原有数据。注意没有判断json里的数据是否与ValueT类型匹配,需要应用层保证
|
||||
///
|
||||
/// \param j nlohmann::json对象
|
||||
/// \param dst 目标变量。
|
||||
/// \return 没找到返回0,找到但不是数组类型-1,有数据返回读到的数据类型。
|
||||
template <typename ValueT>
|
||||
int readPtrVector(const jsonobj& j, std::vector<ValueT*>& dst)
|
||||
{
|
||||
if (!j.is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
int num = int(j.size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
auto* item = new ValueT();
|
||||
j.at(i).template get_to<ValueT>(*item);
|
||||
dst.push_back(item);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/// \brief std::vector<T> -> json
|
||||
/// \details
|
||||
template <typename T>
|
||||
int writeVector(jsonobj& j, const std::vector<T>& p, bool clean=false) {
|
||||
if (clean) {//写入前强制清空
|
||||
j = jsonobj::array();
|
||||
}else if (!j.is_array()) {
|
||||
return -1;
|
||||
}
|
||||
int num = int(p.size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
jsonobj x;
|
||||
to_json(x, p.at(i));
|
||||
j.push_back(x);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/// \brief std::vector<T> -> json
|
||||
/// \details
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename T>
|
||||
int writeVector(jsonobj& j, KeyT key, const std::vector<T>& p, bool clean = false) {
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null() || clean) {//没找到或强制清空
|
||||
j[key] = jsonobj::array(); //先清空
|
||||
}
|
||||
else if (!it->is_array()) {
|
||||
return -1;
|
||||
}
|
||||
int num = int(p.size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
jsonobj x;
|
||||
to_json(x, p.at(i));
|
||||
j[key].push_back(x);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/// \brief std::vector<T*> -> json
|
||||
/// \details
|
||||
template <typename T>
|
||||
int writePtrVector(jsonobj& j, const std::vector<T*>& p, bool clean = false) {
|
||||
if (clean) {//写入前强制清空
|
||||
j = jsonobj::array();
|
||||
}
|
||||
else if (!j.is_array()) {
|
||||
return -1;
|
||||
}
|
||||
int num = int(p.size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
jsonobj x;
|
||||
to_json(x, *p.at(i));
|
||||
j.push_back(x);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/// \brief std::vector<T*> -> json
|
||||
/// \details
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename T>
|
||||
int writePtrVector(jsonobj& j, KeyT key, const std::vector<T*>& p, bool clean=false) {
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null() || clean) {//没找到或强制清空
|
||||
j[key] = jsonobj::array(); //先清空
|
||||
}
|
||||
else if (!it->is_array()) {
|
||||
return -1;
|
||||
}
|
||||
int num = int(p.size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
jsonobj x;
|
||||
to_json(x, *p.at(i));
|
||||
j[key].push_back(x);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/// \brief json --> std::vector<std::shared_ptr<ValueT>>,不会清除原有数据。注意没有判断json里的数据是否与ValueT类型匹配,需要应用层保证
|
||||
///
|
||||
/// \param j nlohmann::json对象
|
||||
/// \param key 键值,类型KeyT支持类型const char *, std::string
|
||||
/// \param dst 目标变量。
|
||||
/// \return 没找到返回0,找到但不是数组类型-1,有数据返回读到的数据类型。
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readSharedPtrVector(const jsonobj& j, KeyT key, std::vector<std::shared_ptr<ValueT>>& dst)
|
||||
{
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null()) {//没找到
|
||||
return 0;
|
||||
}
|
||||
if (!it->is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
int num = int(it->size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
auto item = std::shared_ptr<ValueT>::create();
|
||||
it->at(i).template get_to<ValueT>(*item);
|
||||
dst.append(item);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/// \brief json --> std::vector<std::shared_ptr<ValueT>>,不会清除原有数据。注意没有判断json里的数据是否与ValueT类型匹配,需要应用层保证
|
||||
///
|
||||
/// \param j nlohmann::json对象
|
||||
/// \param dst 目标变量。
|
||||
/// \return 没找到返回0,找到但不是数组类型-1,有数据返回读到的数据类型。
|
||||
template <typename ValueT>
|
||||
int readSharedPtrVector(const jsonobj& j, std::vector<std::shared_ptr<ValueT>>& dst)
|
||||
{
|
||||
if (!j.is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
int num = int(j.size());
|
||||
for (int i = 0; i < num; i++) {
|
||||
auto item = std::shared_ptr<ValueT>::create();
|
||||
j.at(i).template get_to<ValueT>(*item);
|
||||
dst.append(item);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/// \brief std::vector<std::shared_ptr<T>> -> json
|
||||
/// \details
|
||||
template <typename T>
|
||||
int writeSharedPtrVector(jsonobj& j, const std::vector<std::shared_ptr<T>>& p) {
|
||||
if (!j.is_array()) {
|
||||
return -1;
|
||||
}
|
||||
int num = int(p.count());
|
||||
for (int i = 0; i < num; i++) {
|
||||
jsonobj x;
|
||||
to_json(x, *p.at(i));
|
||||
j.push_back(x);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/// \brief std::vector<std::shared_ptr<T>> -> json
|
||||
/// \details
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename T>
|
||||
int writeSharedPtrVector(jsonobj& j, KeyT key, const std::vector<std::shared_ptr<T>>& p) {
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null()) {//没找到
|
||||
j[key] = jsonobj::array(); //先清空
|
||||
}
|
||||
else if (!it->is_array()) {
|
||||
return -1;
|
||||
}
|
||||
int num = int(p.count());
|
||||
for (int i = 0; i < num; i++) {
|
||||
jsonobj x;
|
||||
to_json(x, *p.at(i));
|
||||
j[key].push_back(x);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/** @} vector*/
|
||||
|
||||
|
||||
/** @addtogroup Array
|
||||
* @brief Array <---> jsonobj
|
||||
* @{*/
|
||||
|
||||
/// \brief json --> 数组ValueT dst[maxnum]
|
||||
/// 如果json中的数量超过maxnum,只读maxnum个,不报错。
|
||||
/// \return 返回读到数据个数。<br>
|
||||
/// 0表示没有找到key或数值为空,<br>
|
||||
/// -1表示json[key]不是数组,<br>
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readArray(const jsonobj &j, KeyT key, ValueT* dst, unsigned maxnum)
|
||||
{
|
||||
auto it = j.find(key);
|
||||
if(it == j.end() || it->is_null()) {//没找到
|
||||
return 0;
|
||||
}
|
||||
if(!it->is_array()){ //not array
|
||||
return -1;
|
||||
}
|
||||
uint32_t num = uint32_t(it->size());
|
||||
uint32_t readnum = (num > maxnum) ? maxnum : num;
|
||||
|
||||
for(uint32_t i=0; i< readnum; i++){
|
||||
it->at(i).template get_to<ValueT>(dst[i]);
|
||||
}
|
||||
return int(readnum);
|
||||
}
|
||||
|
||||
/// \brief json --> 数组ValueT dst[maxnum]
|
||||
/// 如果json中的数量超过maxnum,只读maxnum个,不报错。
|
||||
/// \return 返回读到数据个数。<br>
|
||||
/// 0表示没有找到key或数值为空,<br>
|
||||
/// -1表示json[key]不是数组,<br>
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int readAnyArray(const jsonobj& j, KeyT key, ValueT* dst, unsigned maxnum)
|
||||
{
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null()) {//没找到
|
||||
return 0;
|
||||
}
|
||||
if (!it->is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
uint32_t num = uint32_t(it->size());
|
||||
uint32_t readnum = (num > maxnum) ? maxnum : num;
|
||||
|
||||
for (uint32_t i = 0; i < readnum; i++) {
|
||||
from_json(it->at(i), dst[i]);
|
||||
}
|
||||
return int(readnum);
|
||||
|
||||
}
|
||||
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type>
|
||||
int readWStringArray(const jsonobj& j, KeyT key, std::wstring* dst, unsigned maxnum)
|
||||
{
|
||||
auto it = j.find(key);
|
||||
if (it == j.end() || it->is_null()) {//没找到
|
||||
return 0;
|
||||
}
|
||||
if (!it->is_array()) { //not array
|
||||
return -1;
|
||||
}
|
||||
uint32_t num = uint32_t(it->size());
|
||||
uint32_t readnum = (num > maxnum) ? maxnum : num;
|
||||
|
||||
std::string str;
|
||||
for (uint32_t i = 0; i < readnum; i++) {
|
||||
it->at(i).get_to(str);
|
||||
dst[i] = utf8_16(str);
|
||||
}
|
||||
return int(readnum);
|
||||
|
||||
}
|
||||
|
||||
///获取json中名为key的数组长度,不存在或null返回0,不是数组返回-1,数组返回数组长度
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type>
|
||||
int readArrayNum(const jsonobj &j, KeyT key)
|
||||
{
|
||||
auto it = j.find(key);
|
||||
if(it == j.end() || it->is_null()) {//没找到
|
||||
return 0;
|
||||
}
|
||||
if(!it->is_array()){ //not array
|
||||
return -1;
|
||||
}
|
||||
return int(it->size());
|
||||
}
|
||||
|
||||
/// \brief 数组 ValueT src[num] -> json
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int writeArray(jsonobj &j, KeyT key, const ValueT* src, size_t num)
|
||||
{
|
||||
auto tmp = jsonobj::array();
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
tmp.push_back(src[i]);
|
||||
}
|
||||
|
||||
j[key] = tmp;
|
||||
|
||||
return int(num);
|
||||
}
|
||||
|
||||
/// \brief 数组 ValueT src[num] -> json
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type, typename ValueT>
|
||||
int writeAnyArray(jsonobj& j, KeyT key, const ValueT* src, size_t num)
|
||||
{
|
||||
auto tmp = jsonobj::array();
|
||||
jsonobj sub;
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
to_json(sub, src[i]);
|
||||
tmp.push_back(sub);
|
||||
}
|
||||
|
||||
j[key] = tmp;
|
||||
|
||||
return int(num);
|
||||
}
|
||||
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type>
|
||||
int writeWStringArray(jsonobj& j, KeyT key, const std::wstring* src, size_t num)
|
||||
{
|
||||
j[key] = jsonobj::array();
|
||||
|
||||
auto& it = j[key];
|
||||
std::string str;
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
str=utf16_8(src[i]);
|
||||
it.push_back(str);
|
||||
}
|
||||
|
||||
return int(num);
|
||||
}
|
||||
/// \brief 数组 ValueT src[num] -> json
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type>
|
||||
int writeArray(jsonobj& j, KeyT key, const wchar_t ** src, size_t num)
|
||||
{
|
||||
j[key] = jsonobj::array();
|
||||
|
||||
auto& it = j[key];
|
||||
|
||||
USES_CONVERSION;
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
it.push_back(W2A(src[i]));
|
||||
}
|
||||
|
||||
return int(num);
|
||||
}
|
||||
|
||||
/// \brief 数组 ValueT src[num] -> json
|
||||
template <typename KeyT, typename = typename JsonKey<KeyT>::Type>
|
||||
int writeArray(jsonobj& j, KeyT key, const char** src, size_t num)
|
||||
{
|
||||
j[key] = jsonobj::array();
|
||||
|
||||
auto& it = j[key];
|
||||
|
||||
USES_CONVERSION;
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
it.push_back(src[i]);
|
||||
}
|
||||
|
||||
return int(num);
|
||||
}
|
||||
|
||||
|
||||
/** @} Array*/
|
||||
|
||||
|
||||
|
||||
#endif // JSON_VC_WRAPPER_H
|
||||
29
include/json/ksjson.h
Normal file
29
include/json/ksjson.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef LIB_KS_JSON_H
|
||||
#define LIB_KS_JSON_H
|
||||
|
||||
#include "ParaHelper.h"
|
||||
|
||||
/**
|
||||
* @group ksjson
|
||||
* @brief 在nlohmann::json C++类库的基础上扩展的类库。
|
||||
* @details
|
||||
*
|
||||
* nlohmann::json来自:https://github.com/nlohmann/json
|
||||
* 简介: 目录nlohmann下README.md、nlohmann json.pdf
|
||||
* 文档: https://nlohmann.github.io/json/
|
||||
*
|
||||
* 本模块主要实现以下功能:
|
||||
* 1. 支持VC的数据类型,如CString等
|
||||
* 2. 支持从Qt资源文件加载json
|
||||
* 3. json、bson文件接口
|
||||
* 4. 读入参数是支持校验
|
||||
*
|
||||
*/
|
||||
|
||||
#include "jsonReadWithVerify.h"
|
||||
#include "CJsonFile.h"
|
||||
|
||||
#include "jsonVCWrapper.h"
|
||||
|
||||
|
||||
#endif // LIB_KS_JSON_H
|
||||
Reference in New Issue
Block a user