c语言简单json库

文章目录

写在前面

用c语言实现的一个简单json库,极其轻量

仅1个四百多行源码的源文件,和1个头文件

支持对象、数组、数值、字符串类型
github仓库

头文件

对主要的json API的声明

c 复制代码
#ifndef ARCOJSON_ARCOJSON_H
#define ARCOJSON_ARCOJSON_H

#define VERSION v0.1
enum json_type{
    json_type_empty,
    json_type_object,
    json_type_array,
    json_type_string,
    json_type_long
};

typedef struct arco_json{
    enum json_type type;
    int child_num;
    int seq;
    char* key;
    void* value;
    struct arco_json* parent;
    struct arco_json* next;
}arco_json;

/**
 * function: new_json_object
 * 功能:创建一个json对象
 */
arco_json* new_json_object();

/**
 * function: new_json_array
 * 功能:创建一个json数组
 */
arco_json* new_json_array();

/**
 * function:
 * 功能:创建一个json, value是字符串
 */
arco_json* new_json_string(char* value);

/**
 * function: new_json_long
 * 功能:创建一个json, value是long类型的字符串
 * 说明:为了代码简洁, 仅使用long来表示数值
 */
arco_json* new_json_long(long value);

/**
 * function: get_json_type
 * 功能:返回json的类型
 */
int get_json_type(arco_json* json);

/**
 * function: json_object_add
 * 功能:给json对象添加键值对
 */
int json_object_add(arco_json* json, char* key, arco_json* j_add);

/**
 * function: json_array_add
 * 功能:给json数组添加对象
 */
int json_array_add(arco_json* json, arco_json* j_add);

/**
 * function: json_to_string
 * 功能:json对象转json格式字符串
 */
char* json_to_string(arco_json* json);

/**
 * function: string_to_json
 * 功能:json格式字符串转json对象
 */
arco_json* string_to_json(char* str);

/**
 * function: get_string_from_object
 * 功能:通过key获取字符串类型的value
 */
char* get_string_from_object(arco_json* json, char* key);

/**
 * function: get_long_from_object
 * 功能:通过key获取数值类型的value
 */
long get_long_from_object(arco_json* json, char* key);

/**
 * function: get_object_from_object
 * 功能:通过key获取object类型的value
 */
arco_json* get_object_from_object(arco_json* json, char* key);

/**
 * function: get_object_from_array
 * 功能:获取json array的第idx个对象(从0开始
 */
arco_json* get_object_from_array(arco_json* json, int idx);

#endif //ARCOJSON_ARCOJSON_H

源代码

c 复制代码
//
// Created by arco on 2023/8/19.
//
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "arcojson.h"

int g_json_char_num = 0;
char* g_json_str = NULL;

int init_new_json(arco_json* json, int json_type)
{
    json->type = json_type;
    json->child_num = 0;
    json->seq = 0;
    json->key = NULL;
    json->value = NULL;
    json->next = NULL;
}

arco_json* new_json_object()
{
    arco_json* json = malloc(sizeof(arco_json));
    init_new_json(json, json_type_object);
    return json;
}

arco_json* new_json_array()
{
    arco_json* json = malloc(sizeof(arco_json));
    init_new_json(json, json_type_array);
    return json;
}

arco_json* new_json_string(char* value)
{
    // 分配内存
    arco_json* json = malloc(sizeof(arco_json));
    init_new_json(json, json_type_string);
    json->value = (char*) malloc(strlen(value) + 1);
    memcpy(json->value, value, strlen(value) + 1);
    return json;
}

arco_json* new_json_long(long value)
{
    // 分配内存
    arco_json* json = malloc(sizeof(arco_json));
    init_new_json(json, json_type_long);
    json->value = (long*) malloc(sizeof(long));
    *(long*) json->value = value;
    return json;
}

arco_json* new_json_empty()
{
    // 分配内存
    arco_json* json = malloc(sizeof(arco_json));
    init_new_json(json, json_type_empty);
    return json;
}

int get_json_type(arco_json* json)
{
    if (json != NULL) return json->type;
    else return -1;
}

int json_object_add(arco_json* json, char* key, arco_json* j_add)
{
    if (json->type != json_type_object) {
        printf("json type isn't object, can't add kv\n");
        return -1;
    }
    int i;
    // if cur json has none value
    if (json->value == NULL) {
        json->value = j_add;
        j_add->parent = json;
        j_add->key = malloc(strlen(key) + 1);
        memcpy(j_add->key, key, strlen(key) + 1);
        json->child_num++;
    }
    else {
        arco_json* arco = json->value;
        for (i = 0; i < json->child_num - 1; i++) {
            arco = arco->next;
        }
        j_add->key = malloc(strlen(key) + 1);
        memcpy(j_add->key, key, strlen(key) + 1);
        arco->next = j_add;
        j_add->parent = arco->parent;
        json->child_num++;
    }
    return 0;
}

int json_array_add(arco_json* json, arco_json* j_add)
{
    if (json->type != json_type_array) {
        printf("json type isn't array, can't add object\n");
        return -1;
    }
    int i;
    // if cur json has none value
    if (json->value == NULL) {
        json->value = j_add;
        json->child_num++;
    }
    else {
        arco_json* arco = json->value;
        for (i = 0; i < json->child_num - 1; i++) {
            arco = arco->next;
        }
        arco->next = j_add;
        j_add->parent = arco->parent;
        json->child_num++;
    }
    return 0;
}

typedef void (*deal_callback) (char*, ...);

void json_depth_expand(arco_json* json, int depth, deal_callback callback)
{
    if (get_json_type(json) == json_type_array) {
        if (json->key != NULL && depth > 0)
            callback("\"%s\":", json->key);
        callback("[");
        if (json->value != NULL)
            json_depth_expand(json->value, depth + 1, callback);
    }
    if (get_json_type(json) == json_type_object) {
        if (json->key != NULL && depth > 0)
            callback("\"%s\":", json->key);
        callback("{");
        if (json->value != NULL)
            json_depth_expand(json->value, depth + 1, callback);
    }
    if (json->type == json_type_string) {
        callback("\"%s\":", json->key);
        callback("\"%s\"", (char*) json->value);
        if (json->next != NULL) callback(",");
    }
    if (json->type == json_type_long) {
        callback("\"%s\":", json->key);
        callback("%d", *(long*) json->value);
        if (json->next != NULL) callback(",");
    }

    if (get_json_type(json) == json_type_array) {
        callback("]");
        if (json->next != NULL && depth > 0) callback(",");
    }
    if (get_json_type(json) == json_type_object) {
        callback("}");
        if (json->next != NULL && depth > 0) callback(",");
    }

    // 横向搜索
    if (json->next != NULL && depth > 0) {
        json_depth_expand(json->next, depth, callback);
    }
}

void calculate_callback(char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    char str[64];
    vsprintf(str, fmt, args);
    g_json_char_num += (int) strlen(str);
    va_end(args);
}

void tostring_callback(char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    char str[64];
    vsprintf(str, fmt, args);
    strcat(g_json_str, str);
    va_end(args);
}

int calculate_json_str_length(arco_json* json)
{
    g_json_char_num = 0;
    json_depth_expand(json, 0, calculate_callback);
    return g_json_char_num;
}

char* json_to_string(arco_json* json)
{
    int size = calculate_json_str_length(json);
    g_json_str = malloc(size + 1);
    memset(g_json_str, '\0', size + 1);
    json_depth_expand(json, 0, tostring_callback);
    char* json_str = malloc(strlen(g_json_str) + 1);
    memcpy(json_str, g_json_str, strlen(g_json_str) + 1);
    free(g_json_str);
    g_json_str = NULL;
    return json_str;
}

char* str_get_here_to_there(char* str, int position, char c)
{
    int i, size = 1;
    char* dst = NULL;
    for (i = position; i < strlen(str); i++) {
        if (str[i] != c) size++;
        else break;
    }
    dst = malloc(sizeof(char) * size);
    for (i = position; i < strlen(str); i++) {
        if (str[i] != c) dst[i - position] = str[i];
        else {
            dst[i - position] = '\0';
            return dst;
        }
    }
    return NULL;
}

// 返回值是解析的数值的字符串长度(需要跳过的长度
int parse_num_value(char* str, void* value)
{
    int i, start = 0, val_len = 0;
    long rate = 1;
    long* num_val = malloc(sizeof(long));
    char arr[16];
    memset(arr, '\0', sizeof(arr));

    if (str[0] == '-') start = 1;
    val_len += start;

    for (i = start; i < strlen(str) && i < sizeof(arr) - 1; i++) {
        if (str[i] < '0' || str[i] > '9') break;
        arr[i - start] = str[i];
        val_len++;
    }
    for (i = strlen(arr) - 1; i >= 0; i--) {
        *num_val += (arr[i] - '0') * rate;
        rate *= 10;
    }
    if (start) *num_val *= -1;

    *(long*) value = *num_val;

    return val_len;
}

arco_json* string_to_json(char* str)
{
    int i, str_len = (int) strlen(str), need_new = 0;
    int yh_flag = 0, value_flag = 0;
    arco_json* json = new_json_empty();

    arco_json* p_json = json;
    for (i = 0; i < str_len; i++) {
        /**
         * 紧随{或[后的第一个json还没有new出来
         */
        if (need_new) {
            arco_json* j_tmp = new_json_empty();
            p_json->value = j_tmp;
            j_tmp->parent = p_json;
            p_json = p_json->value;
            need_new = 0;
        }
        /**
         * 截取第1-2个引号之间的值作为key, 如果有第3-4个引号那就作为value
         */
        if (str[i] == '"') {
            yh_flag++;
            if (yh_flag == 1) {
                p_json->key = str_get_here_to_there(str, i + 1, '"');
            }
            else if (yh_flag == 2) {

            }
            else if (yh_flag == 3) {
                p_json->value = str_get_here_to_there(str, i + 1, '"');
                p_json->type = json_type_string;
            }
            else if (yh_flag == 4) {
                yh_flag = 0;
            }
        }

        /**
         * 处理冒号后紧随的第一个
         */
        if (value_flag) {
            if ((str[i] >= '0' && str[i] <= '9') || str[i] == '-') {
                p_json->type = json_type_long;
                p_json->value = (long*)malloc(sizeof(long));
                i += parse_num_value(&str[i], p_json->value);
                yh_flag = 0;
            }
            value_flag = 0;
        }

        if (str[i] == ':') {
            value_flag = 1;
        }

        if (str[i] == '{') {
            yh_flag = 0;
            need_new = 1;
            p_json->type = json_type_object;
        }

        if (str[i] == '[') {
            yh_flag = 0;
            need_new = 1;
            p_json->type = json_type_array;
        }

        if (str[i] == ',') {
            // 创建一个空json, 挂到当前json的next
            arco_json* j_tmp = new_json_empty();
            j_tmp->seq = p_json->seq + 1;
            p_json->next = j_tmp;
            // 拷贝上级json
            j_tmp->parent = p_json->parent;
            // 如果是第1个确保当前json的上级的value指向正确
            if (p_json->seq == 0) {
                arco_json* q_json = p_json->parent;
                q_json->value = p_json;
            }
            // 移动当前json
            p_json = p_json->next;
        }

        if (str[i] == '}' || str[i] == ']') {
            arco_json* j_tmp = p_json->parent;
            p_json = j_tmp;
        }
    }
    return json;
}


char* get_string_from_object(arco_json* json, char* key)
{
    if (json == NULL) return NULL;
    if (json->type != json_type_object) return NULL;
    if (json->value == NULL) return NULL;

    arco_json* p_json = json->value;
    while (p_json != NULL) {
        if (p_json->type == json_type_string) {
            if (strcmp((char*) p_json->key, key) == 0) {
                size_t length = strlen((char*) p_json->value);
                char* res = malloc(sizeof(length + 1));
                memcpy(res, p_json->value, length + 1);
                return res;
            }
        }
        p_json = p_json->next;
    }
    return NULL;
}

long get_long_from_object(arco_json* json, char* key)
{
    if (json == NULL) return -1;
    if (json->type != json_type_object) return -1;
    if (json->value == NULL) return -1;

    arco_json* p_json = json->value;
    while (p_json != NULL) {
        if (p_json->type == json_type_long) {
            if (strcmp((char*) p_json->key, key) == 0) {
                long res = *(long*) p_json->value;
                return res;
            }
        }
        p_json = p_json->next;
    }
    return -1;
}

arco_json* get_object_from_object(arco_json* json, char* key)
{
    if (json == NULL) return NULL;
    if (json->type != json_type_object) return NULL;
    if (json->value == NULL) return NULL;

    arco_json* p_json = json->value;
    while (p_json != NULL) {
        if (p_json->type == json_type_object) {
            if (strcmp((char*) p_json->key, key) == 0) {
                arco_json* res = malloc(sizeof(arco_json));
                memcpy(res, p_json, sizeof(arco_json));
                return res;
            }
        }
        p_json = p_json->next;
    }
    return NULL;
}

arco_json* get_object_from_array(arco_json* json, int idx)
{
    if (json == NULL) return NULL;
    if (json->type != json_type_array) return NULL;
    if (json->value == NULL) return NULL;

    int i = 0;
    arco_json* p_json = json->value;
    while (p_json != NULL) {
        if (p_json->type == json_type_object) {
            if (i == idx) {
                arco_json* res = malloc(sizeof(arco_json));
                memcpy(res, p_json, sizeof(arco_json));
                return res;
            }
        }
        p_json = p_json->next;
        i++;
    }
    return NULL;
}

使用示例

请直接看最下面的main函数

c 复制代码
//
// Created by arco on 2023/9/3.
//
#include <string.h>
#include <stdio.h>
#include "arcojson.h"

/**
 * test arco json usage
 */
void create_json_object_test()
{
    arco_json* json = new_json_object();
    json_object_add(json, "key0", new_json_string("value0"));
    arco_json* json1 = new_json_object();
    json_object_add(json1, "key1.0", new_json_string("value1.0"));
    json_object_add(json, "key1", json1);
    arco_json* json2 = new_json_object();
    arco_json* json20 = new_json_object();
    json_object_add(json20, "key2.0.1", new_json_string("value2.0.1"));
    json_object_add(json2, "key2.0", json20);
    json_object_add(json, "key2", json2);

    printf("create_json_obj:%s\n", json_to_string(json));
}

void create_json_object_test_long()
{
    arco_json* json = new_json_object();
    json_object_add(json, "key0", new_json_long(100));
    arco_json* json1 = new_json_object();
    json_object_add(json1, "key1.0", new_json_long(-1));
    json_object_add(json, "key1", json1);
    arco_json* json2 = new_json_object();
    arco_json* json20 = new_json_object();
    json_object_add(json20, "key2.0.1", new_json_long(-1234567));
    json_object_add(json20, "key2.0.2", new_json_string("value2.0.2"));
    json_object_add(json2, "key2.0", json20);
    json_object_add(json, "key2", json2);

    printf("create_json_obj_num:%s\n", json_to_string(json));
}

void create_json_array_test()
{
    arco_json* json = new_json_array();
    arco_json* json0 = new_json_object();
    json_object_add(json0, "key0", new_json_string("value0"));
    arco_json* json1 = new_json_object();
    json_object_add(json1, "key1", new_json_string("value1"));
    arco_json* json2 = new_json_object();
    arco_json* json20 = new_json_object();
    json_object_add(json20, "key2.0", new_json_string("value2.0"));
    json_object_add(json2, "key2", json20);
    json_array_add(json, json0);
    json_array_add(json, json1);
    json_array_add(json, json2);
    printf("create_json_arr:%s\n", json_to_string(json));
}


void create_json_mixed_test()
{
    arco_json* json = new_json_object();
    arco_json* j_o0 = new_json_object();
    json_object_add(j_o0, "ok0", new_json_string("oval0"));

    arco_json* j_a1 = new_json_array();
    arco_json* j_o10 = new_json_object();
    json_object_add(j_o10, "ok10", new_json_string("oval10"));
    arco_json* j_o11 = new_json_object();
    json_object_add(j_o11, "ok11", new_json_string("oval11"));
    json_object_add(j_o11, "ok12", new_json_string("oval12"));
    json_array_add(j_a1, j_o10);
    json_array_add(j_a1, j_o11);

    arco_json* j_o2 = new_json_object();
    arco_json* j_o20 = new_json_object();
    json_object_add(j_o20, "ok20", new_json_string("oval20"));
    json_object_add(j_o20, "ok21", new_json_string("oval21"));
    json_object_add(j_o20, "ok22", new_json_string("oval22"));
    json_object_add(j_o2, "ok2", j_o20);

    json_object_add(json, "obj_1", j_o0);
    json_object_add(json, "arr_1", j_a1);
    json_object_add(json, "obj_2", j_o2);

    printf("create_json_mix:%s\n", json_to_string(json));
}


void create_json_null_test()
{
    arco_json* json_o = new_json_object();
    arco_json* json_a = new_json_array();
    printf("create_json_nul:%s  %s\n", json_to_string(json_o), json_to_string(json_a));
}

void str_to_json_object_test()
{
    char str[] = "{\"key0\":\"value0\",\"key1\":{\"key1.0\":\"value1.0\"},\"key2\":{\"key2.0\":{\"key2.0.1\":\"value2.0.1\"}}}";
    arco_json* json = string_to_json(str);
    printf("str_to_json_obj:%s\n", json_to_string(json));
}

void str_to_json_object_test_long()
{
    char str[] = "{\"key0\":100,\"key1\":{\"key1.0\":-1},\"key2\":{\"key2.0\":{\"key2.0.1\":-1234567,\"key2.0.2\":\"value2.0.2\"}}}";
    arco_json* json = string_to_json(str);
    printf("str_to_json_obj_num:%s\n", json_to_string(json));
}

void str_to_json_array_test()
{
    char str[] = "[{\"key0\":\"value0\"},{\"key1\":\"value1\"},{\"key2\":{\"key2.0\":\"value2.0\"}}]";
    arco_json* json = string_to_json(str);
    printf("str_to_json_arr:%s\n", json_to_string(json));
}

void str_to_json_mixed_test()
{
    char str[] = "{\"obj_1\":{\"ok0\":\"oval0\"},\"arr_1\":[{\"ok10\":\"oval10\"},{\"ok11\":\"oval11\",\"ok12\":\"oval12\"}],\"obj_2\":{\"ok2\":{\"ok20\":\"oval20\",\"ok21\":\"oval21\",\"ok22\":\"oval22\"}}}";
    arco_json* json = string_to_json(str);
    printf("str_to_json_mix:%s\n", json_to_string(json));
}

void str_to_json_null_test()
{
    char str[] = "{}";
    arco_json* json = string_to_json(str);
    char str2[] = "[]";
    arco_json* json2 = string_to_json(str2);
    printf("str_to_json_null:%s  %s\n", json_to_string(json), json_to_string(json2));
}

void json_depth_expand_print(arco_json* json, int depth)
{
//    printf("depth=%d\n", depth);
    if (get_json_type(json) == json_type_array) {
        if (json->key != NULL && depth > 0) printf("\"%s\":", json->key);
        printf("[");
        json_depth_expand_print(json->value, depth + 1);
    }
    if (get_json_type(json) == json_type_object) {
        if (json->key != NULL && depth > 0) printf("\"%s\":", json->key);
        printf("{");
        json_depth_expand_print(json->value, depth + 1);
    }
    if (json->type == json_type_string) {
        printf("\"%s\":", json->key);
        printf("\"%s\"", (char*) json->value);
        if (json->next != NULL) printf(",");
    }
    if (json->type == json_type_long) {
        printf("\"%s\":", json->key);
        printf("%d", *(int*) json->value);
        if (json->next != NULL) printf(",");
    }
    if (json->type == json_type_empty) {
        printf("tmd empty\n");
    }

    if (get_json_type(json) == json_type_array) {
        printf("]");
        if (json->next != NULL && depth > 0) printf(",");
    }
    if (get_json_type(json) == json_type_object) {
        printf("}");
        if (json->next != NULL && depth > 0) printf(",");
    }

    // 横向搜索
    if (json->next != NULL && depth > 0) {
        json_depth_expand_print(json->next, depth);
    }
}

void get_json_value_test()
{
    arco_json* json = new_json_array();
    arco_json* json0 = new_json_object();
    json_object_add(json0, "key00", new_json_long(123));
    json_object_add(json0, "key01", new_json_string("value01"));
    json_object_add(json0, "key02", new_json_string("value02"));
    arco_json* json1 = new_json_object();
    arco_json* json10 = new_json_object();
    json_object_add(json10, "key10", new_json_string("value10"));
    json_object_add(json10, "key11", new_json_long(1234567));
    json_object_add(json1, "key1", json10);
    json_array_add(json, json0);
    json_array_add(json, json1);

    printf("get_json_value_test:%s\n", json_to_string(json));

    arco_json* get_obj_by_idx = get_object_from_array(json, 1);
    printf("get_obj_by_idx:%s\n", json_to_string(get_obj_by_idx));

    arco_json* get_obj_by_key = get_object_from_object(get_obj_by_idx, "key1");
    printf("get_obj_by_key:%s\n", json_to_string(get_obj_by_key));

    char* get_str = get_string_from_object(get_obj_by_key, "key10");
    printf("get_str_value:%s\n", get_str);

    long get_long = get_long_from_object(get_obj_by_key, "key11");
    printf("get_str_value:%ld\n", get_long);

}

int main()
{
    // 创建json对象示例
    create_json_object_test();
    str_to_json_object_test();
    printf("\n");
    // 创建带数值的json对象示例
    create_json_object_test_long();
    str_to_json_object_test_long();
    printf("\n");
    // 创建json数组示例
    create_json_array_test();
    str_to_json_array_test();
    printf("\n");
    // 对象和数组混合示例
    create_json_mixed_test();
    str_to_json_mixed_test();
    printf("\n");
    // null情况示例
    create_json_null_test();
    str_to_json_null_test();
    printf("\n");
    // json对象获取值示例(数组 对象 字符串 数值
    get_json_value_test();

    return 0;
}

编译:arcojson.c arcojson.h example.c三个文件放在同一目录下,然后 gcc arcojson.c example.c -o test

运行: ./test

相关推荐
ahadee2 小时前
蓝桥杯每日真题 - 第19天
c语言·vscode·算法·蓝桥杯
Theliars2 小时前
C语言之字符串
c语言·开发语言
Reese_Cool2 小时前
【数据结构与算法】排序
java·c语言·开发语言·数据结构·c++·算法·排序算法
搬砖的小码农_Sky3 小时前
C语言:结构体
c语言·数据结构
平头哥在等你5 小时前
求一个3*3矩阵对角线元素之和
c语言·算法·矩阵
黎明晓月5 小时前
PostgreSQL提取JSON格式的数据(包含提取list指定索引数据)
postgresql·json·list
尹蓝锐5 小时前
C语言-11-18笔记
c语言
ahadee5 小时前
蓝桥杯每日真题 - 第18天
c语言·vscode·算法·蓝桥杯
就爱六点起5 小时前
C/C++ 中的类型转换方式
c语言·开发语言·c++
猫猫的小茶馆6 小时前
【C语言】指针常量和常量指针
linux·c语言·开发语言·嵌入式软件