JSON
头文件
#include "mln_json.h"
模块名
json
函数/宏
mln_json_init
mln_json_init(j)
描述:初始化JSON类型结点j,该结点类型为NONE.
返回值:无
mln_json_string_init
mln_json_string_init(j, s)
描述:将JSON类型结点j初始化为字符串类型,并赋予mln_string_t *类型的值s。s会被JSON结构接管,调用方需要保证s的内存生命周期以及不可修改s的内容。
返回值:无
mln_json_number_init
mln_json_number_init(j, n)
描述:将JSON类型结点j初始化为数字类型,并赋予double类型的值n。
返回值:无
mln_json_true_init
mln_json_true_init(j)
描述:将JSON类型结点j初始化为true类型。
返回值:无
mln_json_false_init
mln_json_false_init(j)
描述:将JSON类型结点j初始化为false类型。
返回值:无
mln_json_null_init
mln_json_null_init(j)
描述:将JSON类型结点j初始化为null类型。
返回值:无
mln_json_obj_init
int mln_json_obj_init(mln_json_t *j);
描述:将JSON类型结点j初始化为对象类型。
返回值:
0- 成功-1- 失败
mln_json_array_init
int mln_json_array_init(mln_json_t *j);
描述:将JSON类型结点j初始化为数组类型。
返回值:
0- 成功-1- 失败
mln_json_decode
int mln_json_decode(mln_string_t *jstr, mln_json_t *out, mln_json_policy_t *policy);
描述:将JSON字符串jstr解析成数据结构,结果会被放入参数out中。policy为安全策略结构,由mln_json_policy_init进行初始化。
返回值:
0- 成功-1- 失败, 如果policy不为NULL,则需要使用mln_json_policy_error检查具体违反了哪个安全限制条件。
mln_json_destroy
void mln_json_destroy(mln_json_t *j;
描述:释放mln_json_t类型的j节点内存。
返回值:无
mln_json_dump
void mln_json_dump(mln_json_t *j, int n_space, char *prefix);
描述:将json节点j的详细信息输出到标准输出。n_space表示当前缩进空格数,prefix为输出内容的前缀。
返回值:无
mln_json_encode
mln_string_t *mln_json_encode(mln_json_t *j);
描述:由mln_json_t节点结构生成JSON字符串。返回值使用后需要调用mln_string_free进行释放。
返回值:成功返回mln_string_t字符串指针,否则返回NULL
mln_json_obj_search
mln_json_t *mln_json_obj_search(mln_json_t *j, mln_string_t *key);
描述:从对象类型结点j中搜索key为key的value内容。
返回值:成功则返回mln_json_t类型的value,否则返回NULL
mln_json_array_search
mln_json_t *mln_json_array_search(mln_json_t *j, mln_uauto_t index);
描述:从数组类型结点j中搜索下标为index的元素内容。
返回值:成功则返回mln_json_t类型的元素节点,否则返回NULL
mln_json_array_length
mln_uauto_t mln_json_array_length(mln_json_t *j);
描述:获取数组的长度。此时j必须为数组类型。
返回值:数组长度
mln_json_obj_update
int mln_json_obj_update(mln_json_t *j, mln_json_t *key, mln_json_t *val);
描述:将key与val对添加到j JSON节点中。此时,j需为对象类型。若key已经存在,则将原本key和value将会被新参数替换。因此参数key和val在调用后将被j接管。
返回值:成功则返回0,否则返回-1
mln_json_array_append
int mln_json_array_append(mln_json_t *j, mln_json_t *value);
描述:将value加入到数组类型的JSON结构j中。
返回值:成功则返回0,否则返回-1
mln_json_array_update
int mln_json_array_update(mln_json_t *j, mln_json_t *value, mln_uauto_t index);
描述:将value更新到数组类型JSON结构j的下标为index的位置上。若下标不存在,则会失败。
返回值:成功则返回0,否则返回-1
mln_json_reset
void mln_json_reset(mln_json_t *j);
描述:重置JSON节点j数据结构,将其原有数据释放。
返回值:无
mln_json_obj_remove
void mln_json_obj_remove(mln_json_t *j, mln_string_t *key);
描述:将key值为key的键值对从对象类型的JSON结构j中删除并释放。
返回值:存在则返回对应value部分的JSON节点,否则返回NULL
mln_json_array_remove
void mln_json_array_remove(mln_json_t *j, mln_uauto_t index);
描述:将下标为index的元素从数组类型JSON节点上删除并释放。
返回值:存在则返回元素指针,否则返回NULL
is_type
mln_json_is_object(json)
mln_json_is_array(json)
mln_json_is_string(json)
mln_json_is_number(json)
mln_json_is_true(json)
mln_json_is_false(json)
mln_json_is_null(json)
mln_json_is_none(json)
描述:判断mln_json_t结构的json类型,依次分别为:对象、数组、字符串、数字、布尔真、布尔假、NULL、无类型。
返回值:满足条件返回非0,否则返回0
set_type
mln_json_none_type_set(json)
mln_json_object_type_set(json)
mln_json_array_type_set(json)
mln_json_string_type_set(json)
mln_json_number_type_set(json)
mln_json_true_type_set(json)
mln_json_false_type_set(json)
mln_json_null_type_set(json)
描述:给mln_json_t类型的json节点设置类型,依次分别为:无类型、对象、数组、字符串、数字、布尔真、布尔假、NULL。
返回值:无
get_data
mln_json_object_data_get(json)
mln_json_array_data_get(json)
mln_json_string_data_get(json)
mln_json_number_data_get(json)
mln_json_true_data_get(json)
mln_json_false_data_get(json)
mln_json_null_data_get(json)
描述:获取mln_json_t类型的json节点中对应类型的数据部分。类型依次为:对象、数组、字符串、数字、布尔真、布尔假、NULL。
返回值:
- 对象类型为
mln_hash_t类型指针 - 数组类型为
mln_rbtree_t类型指针 - 字符串类型为
mln_string_t类型指针 - 数字类型为
double类型值 - 布尔真为
mln_u8_t类型值 - 布尔假为
mln_u8_t类型值 - NULL类型为
mln_u8ptr_t类型的NULL值
mln_json_policy_init
mln_json_policy_init(policy, _depth, _keylen, _strlen, _elemnum, _kvnum);
描述:对mln_json_policy_t类型的policy进行初始化,剩余参数含义如下:
_depthJSON的最大嵌套层数。解析时,当遇到数组或对象时,嵌套层数会递增。数组或对象解析完成时,嵌套层数会递减。_keylen对象中key的最大长度。_strlen字符串值的最大长度。_elemnum最大数组元素个数。_kvnum最大对象key-value对个数。
返回值:无
mln_json_policy_error
mln_json_policy_error(policy)
描述:从mln_json_policy_t类型的policy获取错误号。这个宏一般用于mln_json_decode返回-1时检查是否有违反安全策略的情况。
返回值:int型错误号,错误号有如下值:
M_JSON_OK没有违反安全策略。M_JSON_DEPTH嵌套层数过多。M_JSON_KEYLEN对象Key的长度超过限制。M_JSON_STRLEN字符串值的长度超过限制。M_JSON_ARRELEM数组元素个数超过限制。M_JSON_OBJKV对象key-value对个数超过限制。
mln_json_parse
int mln_json_parse(mln_json_t *j, mln_string_t *exp, mln_json_iterator_t iterator, void *data)
typedef int (*mln_json_iterator_t)(mln_json_t *, void *);
描述:
从j结点管理的JSON中,根据exp获取其中的匹配的mln_json_t子结点,如果存在匹配的子结点,则会调用iterator回调函数进行处理,data为用户自定义数据,在iterator调用时被传入。
如果我们有如下JSON
{
"a": [1, {
"c": 3
}],
"b": 2
}
exp的写法形如:
| 写法 | 含义 |
|---|---|
a |
获取key为a的值(每个值都保存在mln_json_t结构中) |
b |
获取key为b的值 |
a.0 |
获取key为a,且其值应为数组,再获取数组的第0个下标的元素 |
a.2.c |
获取key为a的值对应的数组,再获取其下标为2的数组元素,该元素应为一个对象,最后获取该元素对象的key为c的值,这个表达式在本例中会导致mln_json_parse返回-1,因为下标为2的数组元素不存在 |
返回值:
0- 成功-1- 失败
mln_json_generate
int mln_json_generate(mln_json_t *j, char *fmt, ...);
描述:
根据fmt给出的格式,利用后续参数填充至j中。
其中,fmt支持如下格式符:
{}- 表示大括号内的是一个对象类型,对象的key与value之间使用:分隔,每组key-value之间以,分隔[]- 表示中括号内的是一个数组类型,每个数组元素之间以,分隔j- 表示可变参部分传入的是一个mln_json_t指针d- 表示可变参部分传入的是一个32位有符号值,例如int或mln_s32_tD- 表示可变参部分传入的是一个64位有符号值,例如long long或mln_s64_tu- 表示可变参部分传入的是一个32位无符号值,例如unsigned int或mln_u32_tU- 表示可变参部分传入的是一个64位无符号值,例如unsigned long long或mln_u64_tF- 表示可变参部分传入的是一个double类型的值t- 表示这个位置填入一个true,这个占位符无需传入对应的可变参数f- 表示这个位置填入一个false,这个占位符无需传入对应的可变参数n- 表示这个位置填入一个null,这个占位符无需传入对应的可变参数s- 表示可变参部分传入的是一个char *类型字符串,例如"Hello"S- 表示可变参部分传入的是一个mln_string_t *类型字符串- 'c' - 表示可变参部分传入的是一个
struct mln_json_call_attr *类型结构,这个结构包含两个成员callback和data,含义是:这个位置的值是由函数callback对data解析而来的
这里有如下注意事项:
fmt中仅可出现上述格式符号,不可存在任何的空格、制表符或者换行符等其他类型符号- 在成功执行本函数后,不可对格式符
j对应的可变参数进行释放(即mln_json_destroy或mln_json_reset)
例如:
mln_json_generate(&j, "[{s:d,s:d,s:{s:d}},d]", "a", 1, "b", 3, "c", "d", 4, 5);
mln_string_t *res = mln_json_encode(&j);
// 得到res中的内容为: [{"b":3,"c":{"d":4},"a":1},5]
返回值:
0- 成功-1- 失败
mln_json_object_iterate
int mln_json_object_iterate(mln_json_t *j, mln_json_object_iterator_t it, void *data);
typedef int (*mln_json_object_iterator_t)(mln_json_t * /*key*/, mln_json_t * /*val*/, void *);
描述:遍历对象j中的每一对key-value对,并使用it对键值对进行处理,data是用户自定义数据,会在it调用时一并传入。
返回值:
0- 成功-1- 失败
mln_json_array_iterate
mln_json_array_iterate(j, it, data);
typedef int (*mln_json_array_iterator_t)(mln_json_t *, void *);
描述:遍历数组j中的每一个元素,并使用it对数组元素进行处理,data是用户自定义数据,会在it调用时一并传入。
返回值:
0- 成功非0- 失败或者其他含义,it返回任何非0值都将中断对数组的遍历
示例
示例1
#include <stdio.h>
#include "mln_string.h"
#include "mln_json.h"
static int callback(mln_json_t *j, void *data)
{
mln_json_number_init(j, *(int *)data);
return 0;
}
static int handler(mln_json_t *j, void *data)
{
mln_json_dump(j, 0, "");
return 0;
}
int main(int argc, char *argv[])
{
int i = 1024;
mln_json_t j, k;
struct mln_json_call_attr ca;
mln_string_t *res, exp = mln_string("protocols.0");
mln_string_t tmp = mln_string("{\"paths\":[\"/mock\"],\"methods\":null,\"sources\":null,\"destinations\":null,\"name\":\"example_route\",\"headers\":null,\"hosts\":null,\"preserve_host\":false,\"regex_priority\":0,\"snis\":null,\"https_redirect_status_code\":426,\"tags\":null,\"protocols\":[\"http\",\"https\"],\"path_handling\":\"v0\",\"id\":\"52d58293-ae25-4c69-acc8-6dd729718a61\",\"updated_at\":1661345592,\"service\":{\"id\":\"c1e98b2b-6e77-476c-82ca-a5f1fb877e07\"},\"response_buffering\":true,\"strip_path\":true,\"request_buffering\":true,\"created_at\":1661345592}");
if (mln_json_decode(&tmp, &j, NULL) < 0) { //解码字符串,生成mln_json_t的结点
fprintf(stderr, "decode error\n");
return -1;
}
mln_json_parse(&j, &exp, handler, NULL); //获取该JSON中key为protocols的数组的第1个元素,并交给handler处理
//填充用户自定义数据解析结构
ca.callback = callback;
ca.data = &i;
//利用格式符生成JSON结构
mln_json_init(&k);//mln_json_generate前一定要对未初始化的json变量进行初始化
if (mln_json_generate(&k, "[{s:d,s:d,s:{s:d}},d,[],j,c]", "a", 1, "b", 3, "c", "d", 4, 5, &j, &ca) < 0) {
fprintf(stderr, "generate failed\n");
return -1;
}
mln_json_generate(&k, "[s,d]", "g", 99);//这两个元素会被加入到k数组中
res = mln_json_encode(&k); //对生成的结构生成相应的JSON字符串
mln_json_destroy(&k); //注意,这里不要释放j,因为k会释放j中的内存
if (res == NULL) {
fprintf(stderr, "encode failed\n");
return -1;
}
write(STDOUT_FILENO, res->data, res->len);
write(STDOUT_FILENO, "\n", 1);
mln_string_free(res);
return 0;
}
本例的执行结果如下:
type:string val:[http]
[{"b":3,"c":{"d":4},"a":1},5,[],{"preserve_host":false,"name":"example_route","destinations":null,"methods":null,"tags":null,"hosts":null,"response_buffering":true,"snis":null,"https_redirect_status_code":426,"headers":null,"request_buffering":true,"sources":null,"strip_path":true,"protocols":["http","https"],"path_handling":"v0","created_at":1661345592,"id":"52d58293-ae25-4c69-acc8-6dd729718a61","updated_at":1661345592,"paths":["/mock"],"regex_priority":0,"service":{"id":"c1e98b2b-6e77-476c-82ca-a5f1fb877e07"}},1024,"g",99]
第一行为handler中的mln_dump输出,第二行为mln_json_encode生成的字符串。
示例2
#include "mln_json.h"
#include "mln_log.h"
static int obj_iterator(mln_json_t *k, mln_json_t *v, void *data)
{
mln_string_t *s = mln_json_string_data_get(k);
int i = (int)mln_json_number_data_get(v);
mln_log(none, "%S: %d\n", s, i);
return 0;
}
static int array_iterator(mln_json_t *j, void *data)
{
return mln_json_object_iterate(j, obj_iterator, data);
}
static int handler(mln_json_t *j, void *data)
{
return mln_json_array_iterate(j, array_iterator, data);
}
static void parse(mln_string_t *p)
{
mln_json_t j;
mln_json_policy_t policy;
mln_string_t exp = mln_string("resolutions");
mln_json_policy_init(policy, 3, 11, 10, 1, 2);
mln_json_decode(p, &j, &policy);
mln_json_parse(&j, &exp, handler, NULL);
mln_json_destroy(&j);
}
int main(void)
{
mln_string_t p = mln_string("{\"name\":\"Awesome 4K\",\"resolutions\":[{\"width\":1280,\"height\":720}]}");
parse(&p);
return 0;
}
运行结果如下:
width: 1280
height: 720