C言語はcJsonを使ってjsonを解析します.
C言語でjsonを解析します. cjsonライブラリ cjsonオブジェクトタイプと構造体 cjsonのいくつかの常用インターフェース .cjsonライブラリをさらにパッケージ化する .試験事例 を呼び出します.追加 cjsonライブラリ
ギthubまたはgitee上でcjsonは、ライブラリ内の
cjsonオブジェクトタイプと構造体
json文字列の解析は使い終わったら、解放空間を覚えてください.
cjsonライブラリにはいくつかの関数が実装されています.は、jsonファイルパスに従って、ファイルをjsonオブジェクトに変換し、失敗してNULL に戻る.は、親オブジェクトにおいて、キーパッドペアの名前から対応するサブオブジェクトを取得し、失敗してNULL に戻る.は、親オブジェクトにおいて、キーパッドペアの名前に基づいて、対応する文字列 を取得する.は、親オブジェクトにおいて、キーパッドペアの名前から対応する数値 を取得する.は、親オブジェクトにおいて、行列型のサブオブジェクトを取得し、配列メンバー数 comon.cのコードファイルを作成し、comon.hのヘッダファイルを作成します.comon.cの具体的なパッケージコードは以下の通りです.
iperfの関数がcJSONをカプセル化しているのを見て、いいと思います.
ギthubまたはgitee上でcjsonは、ライブラリ内の
cJSON.c
とcJSON.h
を使用すれば良い.以下はcjsonを使った事例です.参考にしてください.クリックして私のcJosnの使用例をダウンロードします.cjsonオブジェクトタイプと構造体
/* cJSON Types: */
#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) /* raw json */
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child; // , , NULL
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of,
or is in the list of subitems of an object. */
char *string; // , , ,
} cJSON;
cjsonのいくつかの常用インターフェースjson文字列の解析は使い終わったら、解放空間を覚えてください.
// json , cJSON , ,
// cJSON , cJSON_Delete(cJSON *c) .
cJSON * cJSON_Parse(const char *value);
cjsonオブジェクト空間のリリース// cJSON_Parse,cJSON_CreateObject create
void cJSON_Delete(cJSON *c);
cjsonオブジェクトのタイプを判断すると、次のような種類があります./* These functions check the type of an item cJSON */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
cjsonオブジェクトを作成して、開放空間を覚えてください./* cjson These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
作成または変更されたcjsonオブジェクトを文字列として出力し、自分でファイルに保存します.文字列を使い切ると、スペースが解放されます./* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
アプリケーションとリリーススペース、cJSON_Print返した文字列空間は、cJSON_が使用できます.freeで釈放するCJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
cjsonライブラリをさらにパッケージ化cjsonライブラリにはいくつかの関数が実装されています.
cJSON * json_parse(const char *path);
//pjson cjson , pitemname ,
const cJSON * json_get_object(const cJSON *pjson, const char *pitemname);
//pjson cjson , pitemname ,pdft , ,
const char * json_get_string(const cJSON *pjson, const char *pitemname, const char *pdft);
//pjson cjson , pitemname ,pdft , ,
int json_get_number(const cJSON *pjson, const char *pitemname, int pdft);
int json_get_array_size(const cJSON *pjson, const char *pitemname)
#include
#include
#include
#include "common.h"
#define in_range(c, lo, up) ((unsigned char)c >= lo && (unsigned char)c <= up)
#define isdigit(c) in_range(c, '0', '9')
/**
******************************************************************************
* @brief
* @param[in] : *pstr :
* @retval >= 0 :
* @retval < 0 :
******************************************************************************
*/
int
str2i(const char *pstr)
{
int ret = 0;
if (!(*pstr && isdigit(*pstr)))
return -1;
do
{
ret = ret * 10 + (*pstr - '0');
pstr++;
} while (*pstr && isdigit(*pstr));
return ret;
}
/**
******************************************************************************
* @brief json json
* @param[in] *path :
* @retval cJSON * : NULL
******************************************************************************
*/
cJSON *
json_parse(const char *path)
{
int file_size = 0;
FILE *fp = NULL;
char *pstr = NULL;
cJSON *pjson = NULL;
int ret = 0;
/*
* 1.
* 2. ,
* 3. cjson
* 4.
*/
do
{
if (!path)
{
break;
}
fp = fopen(path, "rb");
if (NULL == fp)
{
break;
}
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
pstr = malloc(file_size + 1);
if (!pstr)
{
break;
}
pstr[file_size] = 0; //last = 1
if (file_size != (int)fread(pstr, 1, file_size, fp))
{
break;
}
cJSON_Print(pjson);
pjson = cJSON_Parse(pstr);
ret = pjson ? 1 : 0;
} while (0);
if (fp)
{
fclose(fp);
}
if (pstr)
{
free(pstr);
}
return ret ? pjson : NULL;
}
/**
******************************************************************************
* @brief json
* @param[in] *pjson : json
* @param[in] *pitemname :
* @retval
******************************************************************************
*/
const cJSON *
json_get_object(const cJSON *pjson,
const char *pitemname)
{
/*
* 1. (.)
* 2. array, [%d]
*/
int pos;
char item[64];
char *ptmp;
char *ptr = NULL;
const char *pstr;
const cJSON *parray;
const cJSON *pobject = pjson;
if (!pjson || !pitemname || !pitemname[0] || (strlen(pitemname) >= sizeof(item)))
{
return NULL;
}
strncpy(item, pitemname, sizeof(item));
char* str = item;
// "."
while (pobject && (pstr = strtok_r(str, ".", &ptr)))
{
str = NULL;
if ((ptmp = strstr(pstr, "["))) //Array
{
if (0 > (pos = str2i(ptmp + 1)))
{
break;
}
ptmp[0] = 0;
parray = cJSON_GetObjectItem(pobject, pstr);
if (!cJSON_IsArray(parray) || (pos >= cJSON_GetArraySize(parray)))
{
break;
}
pobject = cJSON_GetArrayItem(parray, pos);
}
else //object
{
pobject = cJSON_GetObjectItem(pobject, pstr);
}
}
return pobject;
}
/**
******************************************************************************
* @brief json
* @param[in] *pjson : json
* @param[in] *pitemname :
* @param[in] *pdft :
* @retval ( )
******************************************************************************
*/
const char *
json_get_string(const cJSON *pjson,
const char *pitemname,
const char *pdft)
{
const char *pstr;
const cJSON *pobject;
do
{
if (!pjson || !pitemname || !pitemname[0])
{
break;
}
if (!(pobject = json_get_object(pjson, pitemname)))
{
break;
}
pstr = cJSON_GetStringValue(pobject);
return pstr ? pstr : "";
} while (0);
return pdft ? pdft : "";
}
/**
******************************************************************************
* @brief json
* @param[in] *pjson : json
* @param[in] *pitemname :
* @param[in] dft :
* @retval
******************************************************************************
*/
int
json_get_number(const cJSON *pjson,
const char *pitemname,
int dft)
{
const cJSON *pobject;
do
{
if (!pjson || !pitemname || !pitemname[0])
{
break;
}
if (!(pobject = json_get_object(pjson, pitemname)))
{
break;
}
if (!cJSON_IsNumber(pobject))
{
break;
}
return pobject->valueint;
} while (0);
return dft;
}
/**
******************************************************************************
* @brief json
* @param[in] *pjson : json
* @param[in] *pitemname :
* @retval
******************************************************************************
*/
int
json_get_array_size(const cJSON *pjson,
const char *pitemname)
{
const cJSON *pobject;
do
{
if (!pjson || !pitemname || !pitemname[0])
{
break;
}
if (!(pobject = json_get_object(pjson, pitemname)))
{
break;
}
if (!cJSON_IsArray(pobject))
{
break;
}
return cJSON_GetArraySize(pobject);
} while (0);
return 0;
}
common.hファイル#ifndef _COMMON_H
#define _COMMON_H
#include "./json/cJSON.h"
#if defined(__cplusplus)
extern "C"
{
#endif
extern const cJSON *
json_get_object(const cJSON *pjson,
const char *pitemname);
extern const char *
json_get_string(const cJSON *pjson,
const char *pitemname,
const char *pdft);
extern int
json_get_number(const cJSON *pjson,
const char *pitemname,
int dft);
extern int
json_get_array_size(const cJSON *pjson,
const char *pitemname);
extern cJSON *
json_parse(const char *path);
#if defined(__cplusplus)
}
#endif
#endif
テストケースの呼び出しconfig.json
ファイルを作成しました.ファイルの内容は以下の通りです.{
"multicastIp": "239.0.0.10",
"multicastPort": 8805,
"services": [
"192.168.0.118",
"172.19.75.111",
"172.19.75.45",
"172.19.75.234"
]
}
mian.cのテストファイルを作成します.#include
#include
#include
#include "common.h"
#define CONFIG_FILE "./config.json"
typedef struct{
int muticast_port; //
char * muticast_ip; // IP
int service_count; //
char** service_ips; // ip
} config_info_t;
config_info_t config; // ,
/**
******************************************************************************
* @brief
* @retval 0: , -1:
******************************************************************************
*/
int config_init()
{
char key[64];
cJSON * obj = NULL;
// json
if (NULL == (obj = json_parse(CONFIG_FILE)))
{
exit(1);
}
// json
config.muticast_port = json_get_number(obj, "multicastPort", 8805);
config.muticast_ip = strdup(json_get_string(obj, "multicastIp", "239.0.0.10"));
config.service_count = json_get_array_size(obj, "services");//
// ,
if (NULL == (config.service_ips = (char**) malloc(sizeof(char*) * config.service_count)))
{
cJSON_Delete(obj); //
return -1;
}
//
memset(key, 0, sizeof(key));
for (int i = 0; i < config.service_count; ++i)
{
snprintf(key, sizeof(key), "services[%d]", i);
config.service_ips[i] = strdup(json_get_string(obj, key, NULL));
}
cJSON_Delete(obj); // json
return 0;
}
/**
******************************************************************************
* @brief ,
* @param[in] * pconfig :
******************************************************************************
*/
void config_destroy()
{
if (config.muticast_ip)
{
free(config.muticast_ip);
config.muticast_ip = NULL;
}
if (config.service_ips)
{
for (int i = 0; i < config.service_count; ++i)
{
if (config.service_ips[i])
{
free(config.service_ips[i]);
config.service_ips[i] = NULL;
}
}
free(config.service_ips);
config.service_ips = NULL;
}
}
int main(int argc, char * argv[])
{
config_init();
printf(" :\t %d
", config.muticast_port);
printf(" IP:\t %s
", config.muticast_ip);
printf(" :\t %d
", config.service_count);
for (int i = 0; i < config.service_count; i++)
{
printf(" %d:\t %s
", i, config.service_ips[i]);
}
config_destroy();
}
テストの結果は以下の通りですlmz@lmz-X280:~/ /code/c/test/cJsonTest$ make all
gcc -fPIC -c -o common.o common.c
gcc -fPIC -c -o cJSON.o ./json/cJSON.c
gcc main.c -o main common.o cJSON.o
lmz@lmz-X280:~/ /code/c/test/cJsonTest$ ./main
: 8805
IP: 239.0.0.10
: 4
0: 192.168.0.118
1: 172.19.75.111
2: 172.19.75.45
3: 172.19.75.234
追加iperfの関数がcJSONをカプセル化しているのを見て、いいと思います.
common.c
に入れて、cJSONのより良い操作に便利です.必要な#include
は、printfを用いてcJSONオブジェクトを作成する機能である.
/* Helper routine for building cJSON objects in a printf-like manner.
**
** Sample call:
** j = json_printf("foo: %b bar: %d bletch: %f eep: %s", b, i, f, s);
**
** The four formatting characters and the types they expect are:
** %b boolean int
** %d integer int64_t
** %f floating point double
** %s string char *
** If the values you're passing in are not these exact types, you must
** cast them, there is no automatic type coercion/widening here.
**
** The colons mark the end of field names, and blanks are ignored.
**
** This routine is not particularly robust, but it's not part of the API,
** it's just for internal iperf3 use.
*/
cJSON*
json_printf(const char *format, ...)
{
cJSON* o;
va_list argp;
const char *cp;
char name[100];
char* np;
cJSON* j;
o = cJSON_CreateObject();
if (o == NULL)
return NULL;
va_start(argp, format);
np = name;
for (cp = format; *cp != '\0'; ++cp) {
switch (*cp) {
case ' ':
break;
case ':':
*np = '\0';
break;
case '%':
++cp;
switch (*cp) {
case 'b':
j = cJSON_CreateBool(va_arg(argp, int));
break;
case 'd':
j = cJSON_CreateNumber(va_arg(argp, int64_t));
break;
case 'f':
j = cJSON_CreateNumber(va_arg(argp, double));
break;
case 's':
j = cJSON_CreateString(va_arg(argp, char *));
break;
default:
va_end(argp);
return NULL;
}
if (j == NULL) {
va_end(argp);
return NULL;
}
cJSON_AddItemToObject(o, name, j);
np = name;
break;
default:
*np++ = *cp;
break;
}
}
va_end(argp);
return o;
}
cJSON* json_printf(const char *format, ...);
使用例
int main(int argc, char * argv[])
{
char ip[] = "127.0.0.1";
int port = 8080;
cJSON * cjobj = cJSON_CreateObject();
/*printf */
cJSON * cjip = json_printf("ip: %s port: %d", ip, port);
cJSON_AddItemToObject(cjobj, "service", cjip);
char * p = cJSON_Print(cjobj);
printf("%s
", p);
cJSON_free(p);
cJSON_Delete(cjobj);
}