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 *类型的值ss会被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进行初始化。若解码失败,out会被自动清理,无需手动调用mln_json_destroy

返回值:

  • 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_u32_t flags);

描述:由mln_json_t节点结构生成JSON文本字符串。返回值使用后需要调用mln_string_free进行释放。

标志位:

  • 0 - 输出为标准JSON文本格式(默认)
  • M_JSON_ENCODE_UNICODE (0x1) - 将非ASCII字符(如中文)转义为\uXXXX形式

返回值:成功返回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);

描述:将keyval对添加到对象类型的JSON节点j中。若key已经存在,则原有的key和value将被新参数替换。函数内部会拷贝keyval的内容,调用方无需为其分配堆内存。

返回值:成功则返回0,否则返回-1

mln_json_obj_element_num

mln_size_t mln_json_obj_element_num(mln_json_t *j);

描述:获取对象类型JSON节点j中键值对的数量。

返回值:键值对数量

mln_json_array_append

int mln_json_array_append(mln_json_t *j, mln_json_t *value);

描述:将value追加到数组类型的JSON结构j末尾。函数内部会拷贝value的内容。

返回值:成功则返回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的位置。若下标不存在,则会失败。函数内部会拷贝value的内容。

返回值:成功则返回0,否则返回-1

mln_json_reset

void mln_json_reset(mln_json_t *j);

描述:重置JSON节点j,释放其所持有的数据,并将类型恢复为NONE

返回值:无

mln_json_obj_remove

void mln_json_obj_remove(mln_json_t *j, mln_string_t *key);

描述:将key为key的键值对从对象类型的JSON结构j中删除并释放。

返回值:无

mln_json_array_remove

void mln_json_array_remove(mln_json_t *j, mln_uauto_t index);

描述:删除并释放数组类型JSON节点j中的最后一个元素。参数index必须等于最后一个有效下标(即length - 1),仅在调试构建中用于断言检查。

返回值:无

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节点中对应类型的数据部分。

返回值:

  • 对象类型为mln_json_obj_t类型指针
  • 数组类型为mln_array_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进行初始化,其余参数含义如下:

  • _depth JSON的最大嵌套层数。解析时,遇到数组或对象会递增嵌套层数,解析完成后递减。值为0时表示不限制。

  • _keylen 对象中key的最大长度。值为0时表示不限制。

  • _strlen 字符串值的最大长度。值为0时表示不限制。

  • _elemnum 最大数组元素个数。值为0时表示不限制。

  • _kvnum 最大对象键值对个数。值为0时表示不限制。

返回值:无

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 对象键值对个数超过限制。

mln_json_fetch

int mln_json_fetch(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 *);

描述:

根据表达式exp从JSON节点j中查找匹配的子结点。如果找到匹配的子结点且iterator不为NULL,则调用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.1.c 获取key为a的数组中下标为1的对象,再获取其key为c的值
a.2.c 下标2的元素不存在,mln_json_fetch返回-1

返回值:

  • 0 - 成功
  • -1 - 失败

mln_json_generate

int mln_json_generate(mln_json_t *j, char *fmt, ...);

描述:

根据fmt给出的格式,利用后续可变参数填充至j中。

fmt支持如下格式符:

  • {} - 表示大括号内是一个对象类型,key与value之间使用:分隔,每组键值对之间以,分隔
  • [] - 表示中括号内是一个数组类型,每个数组元素之间以,分隔
  • j - 对应的可变参数是mln_json_t指针
  • d - 对应的可变参数是32位有符号值,例如intmln_s32_t
  • D - 对应的可变参数是64位有符号值,例如long longmln_s64_t
  • u - 对应的可变参数是32位无符号值,例如unsigned intmln_u32_t
  • U - 对应的可变参数是64位无符号值,例如unsigned long longmln_u64_t
  • F - 对应的可变参数是double类型的值
  • t - 此位置填入一个true,不需要对应的可变参数
  • f - 此位置填入一个false,不需要对应的可变参数
  • n - 此位置填入一个null,不需要对应的可变参数
  • s - 对应的可变参数是char *类型字符串
  • S - 对应的可变参数是mln_string_t *类型字符串
  • c - 对应的可变参数是struct mln_json_call_attr *类型结构,包含callbackdata两个成员,表示由callback函数配合data生成该位置的值

注意事项:

  1. fmt中仅可出现上述格式符号,不可包含空格、制表符或换行符等其他字符。
  2. 成功执行本函数后,格式符j对应的可变参数所指向的JSON节点将被j接管,调用方不可再对其调用mln_json_destroymln_json_reset

例如:

mln_json_init(&j);
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, 0);

// 得到res中的内容为: [{"a":1,"b":3,"c":{"d":4}},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中的每一对键值对,并使用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}");

    /* 解码字符串,生成mln_json_t的结点 */
    if (mln_json_decode(&tmp, &j, NULL) < 0) {
        fprintf(stderr, "decode error\n");
        return -1;
    }

    /* 获取key为protocols的数组的第0个元素,并交给handler处理 */
    mln_json_fetch(&j, &exp, handler, NULL);

    /* 填充用户自定义数据解析结构 */
    ca.callback = callback;
    ca.data = &i;

    /* mln_json_generate前一定要对未初始化的json变量进行初始化 */
    mln_json_init(&k);
    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;
    }
    /* 这两个元素会被追加到k数组中 */
    mln_json_generate(&k, "[s,d]", "g", 99);
    /* 对生成的结构编码为JSON字符串 */
    res = mln_json_encode(&k, 0);

    /* 注意:不要释放j,因为j的内容已被k接管 */
    mln_json_destroy(&k);

    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]
[{"a":1,"b":3,"c":{"d":4}},5,[],{"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},1024,"g",99]

第一行为handler中的mln_json_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_fetch(&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

results matching ""

    No results matching ""