1、cJson的简单介绍
cJson - github网址
概述
一般使用cJson是,需要将json文本转化为json对象–编码,将json对象转化为json文本–解析。
git clone https://github.com/DaveGamble/cJSON.git
后留意cJSON.h和cJSON.h两个文件。
1、cJson的介绍
cJson是一个数据结构,里面含有prev next child 等指针用于获取json数据的具体值 typedef struct cJSON { struct cJSON *next; struct cJSON *prev; struct cJSON *child; //type是指,该节点的数据类型 int type; //字符串获取的变量 char *valuestring; //int值获取的变量 int valueint; //double 值获取的变量 double valuedouble; //暂未接触 char *string; } cJSON; //int type的值,去这几种 //#define cJSON_Invalid (0) //#define cJSON_False (1 << 0) //#define cJSON_True (1 << 1) //#define cJSON_NULL (1 << 2) //#define cJSON_Number (1 << 3) //#define cJSON_String (1 << 4) //#define cJSON_Array (1 << 5) //#define cJSON_Object (1 << 6) //#define cJSON_Raw (1 << 7) //编码方法 cJson* cJSON_Parse(char *); //解码方法 char* cJSON_Print(cJson *);
复制
2、编码
//1、声明一个简单的字符串 char *jsonText = "{\"name\":\"zhangsan\",\"age\":18,\"price\":21.0}"; //2、将字符串给到cJSON_Parse方法,json!=null,就会给到一个cJson结构。 cJSON *json = cJSON_Parse(jsonText); // 获取到string的值 json->valuestring // 获取到string的值 json->valuestring // 获取到int的值 json->valueint // 获取到int的值 json->valuedouble //以上三种方法获取对应类型的字段的值 // 3、通过根json去获取到具体的一个字段(name) cJSON *jsonValue = cJSON_GetObjectItem(json, "name"); //返回的也是一个cJson结构,获取值与上面相同操作
复制
3、解码
//1.将一个cJOSN的结构,变量一个json文本 char * cJSON_Print(cJSON *);
复制
2、OpenHarmony项目实现
1、项目创建
IDE版本:
DevEco Studio 3.1.1 Release
Build Version: 3.1.0.501, built on June 20, 2023
Build #DS-223.8617.56.36.310501
Runtime version: 17.0.6+10-b829.5 amd64
按照官方的要求创建一个Native项目
2、目录及文件介绍
1、cJSON.c是cjson实现的源码
2、cJSON.h是cJSON.c的头文件,以上两个文件可以在上面git中获取。
3、CMakeList.exe 文件时配置cmake编译的配置文件
# the minimum version of CMake. cmake_minimum_required(VERSION 3.4.1) project(MyFirstCpp) # 定义一个变量,并赋值为当前模块cpp目录 set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) # 添加头文件.h目录,包括cpp,cpp/include,告诉cmake去这里找到代码引入的头文件 include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include) # hiloglib -- 给c层打印日志使用的 find_library( hilog_lib hilog_ndk.z ) # 声明一个产物libentry.so,SHARED表示产物为动态库,hello.cpp为产物的源代码 # !!!注意:如果使用源码一起编译是,需要将源文件添加进来,例如:hello.cpp cjson.c add_library(entry SHARED hello.cpp cjson.c) # 声明产物entry链接时需要的三方库libace_napi.z.so # 这里直接写三方库的名称是因为它是在ndk中,已在链接寻址路径中,无需额外声明 # 添加的编译so库 target_link_libraries(entry PUBLIC ${hilog_lib} libace_napi.z.so)
复制
4、Index.ets 布局文件
//伪代码 import testNapi from 'libentry.so' json: string = "{\"name\":\"zhangsan\",\"age\":18,\"price\":21.5}"; Button().onClick(() => { let json = testNapi.modifyJson(this.json,this.inputText); hilog.info(0x0000, 'testTag', 'cjson name = %{public}d', json); }
复制
5、LogUtils.ts 是一个打印日志的工具
export class LogUtils{ static Tag:string = 'MyFirstCpp'; static i(...args){ hilog.info(0x0000, LogUtils.Tag, '%{public}s', args); } static d(msg:string){ hilog.debug(0x0000, LogUtils.Tag, '%{public}s', msg); } static e(msg:string){ hilog.error(0x0000, LogUtils.Tag, '%{public}s', msg); } }
复制
6、hello.cpp文件方法配置介绍
初始化创建一个Native 项目在hello.cpp文件中默认存在如下代码:
EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[] = { {"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr}, //{"modifyJson", nullptr, ModifyJson, nullptr, nullptr, nullptr, napi_default, nullptr}, }; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; } EXTERN_C_END static napi_module demoModule = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, .nm_register_func = Init, .nm_modname = "entry", .nm_priv = ((void *)0), .reserved = {0}, }; extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
复制
其中 napi_property_descriptor 变量里面存在的是c对应js的方法。需要添加不同的方法(js调用的方法)需要在这里声明。
{“add”, nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr}
目前按照以上格式,替换一下【“add”】 和 【Add】的值。
eg:
我现在要声明一个modifyJson方法,如下参数,js层也一并需要声明。
{"modifyJson", nullptr, ModifyJson, nullptr, nullptr, nullptr, napi_default, nullptr}
复制
在js层也需要声明条用的方法如下:
在src/main/cpp/types/libentry/index.d.ts文件下:
export const add: (a: number, b: number) => number;
复制
eg:
添加 modifyJson 方法
export const add: (a: number, b: number) => number; //json 是json字符串;nameValue 是修改name字段的值 export const modifyJson:(json:string,nameValue:string)=>string;
复制
3、代码介绍
首先NDK开发使用的是js的napi库。需要注意的是js和C/C++之间的数据类型之间的切换。
1、napi与C/C++之间数据类型切换
anpi 中的数据目前使用一个napi_value (js层接收的类型)
C/C++中的数据类型目前用到了 string,char*,int, double
下面就是 anpi_value 转为 C/C++ string、int、double
/** * 获取 js中的string 到 C中使用 * @param env * @param value * @return */ static const string get_native_string_value(napi_env env,napi_value value){ //不知道字符串长度,先获取一下,拿到字符串的真实长度 size_t textLen; napi_get_value_string_utf8(env, value, NULL, 0, &textLen); //得到了真实的长度,需要在次长度上+1(不全\0) char text[textLen+1]; napi_get_value_string_utf8(env, value,text, sizeof(text), &textLen); //返回的是std:string,记得导入 using namespace std; string buf(text, textLen); return buf; } /** * 获取 js 中的 int 到 C中使用 * @param env * @param _msg * @return */ static int get_native_int_value(napi_env env,napi_value value){ int32_t iNum; napi_get_value_int32(env, value, &iNum); return iNum; } /** * 获取 js 中的double 到C中使用 * @param env * @param _msg * @return */ static double get_native_double_value(napi_env env,napi_value value){ double dNum; napi_get_value_double(env, value, &dNum); return dNum; }
复制
下面就是 C/C++ string、int、double 转为 napi_value(可以直接返回给js层的类型)
/** * 将c中的char* 构建一个 js的string类型 * @return */ static napi_value return_string_value(napi_env env,char *_msg){ napi_value msg; napi_create_string_utf8(env, _msg, strlen(_msg), &msg); return msg; } /** * 将c中的int 构建一个 js的int类型 * @return */ static napi_value return_int_value(napi_env env,int _msg){ napi_value i; napi_create_int32(env, _msg, &i); return i; } /** * 将c中的double 构建一个 js的double类型 * @return */ static napi_value return_double_value(napi_env env,double _msg){ napi_value d; napi_create_double(env, _msg, &d); return d; }
复制
4、核心处理
static napi_value ModifyJson(napi_env env, napi_callback_info info) { napi_value modifyJson; // OH_LOG_INFO c的日志,需要按照CmakeList.txt 导入库。不然无法访问 OH_LOG_INFO(LOG_APP,"ModifyJson start"); //1、获取js中传过来的参数,放入 args 数组中,argc 是有两个参数 size_t argc = 2; napi_value args[2] = {nullptr}; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); //2.获取对应参数的值 string jsonText = get_native_string_value(env, args[0]); //3.获取修改的文本 string newName = get_native_string_value(env, args[1]); //4.编码json cJSON *jsonObj = cJSON_Parse(jsonText.c_str()); //5.获取字段为 name 的json对象,然后操作这个对象获取值和修改值 cJSON *nameValueObj = cJSON_GetObjectItemCaseSensitive(jsonObj, "name"); if(NULL == nameValueObj){ //Undefined_value 和 get_native_string_value,类似只是返回 char* -> napi_value return Undefined_value(env, "NULL == nameValueObj"); } //6.修改 nameValueObj 值,注意:赋值要使用 strdup 方法进行包一层,不然在 cJSON_Delete 释放时会报错 //之前一个是将char* 赋值到valuestring 中,不进行strdup释放的时候回报错 // nameValueObj->valuestring = strdup(newName.c_str()); //查看cjson源码发现,自带一个修改指定字段的值 cJSON_SetValuestring cJSON_SetValuestring(nameValueObj, newName.c_str()); //7.修改完值后需要重新进行对 jsonObj 进行 解码 json 再返回json到js层 char *newJson = cJSON_Print(jsonObj); //8、返回新的json字符串 napi_create_string_utf8(env, newJson, strlen(newJson), &modifyJson); //释放 jsonObj cJSON_Delete(jsonObj); return modifyJson; }
复制
以上就是简单的将cJson 移植到OpenHarmony。希望可以帮助到大家!!!