首先是定义json结构和接口
#ifndef CJSON_CJSON_H
#define CJSON_CJSON_H
#include <basetsd.h>
typedef enum type
{
STRING_1,
OBJECT_1,
BOOL_1,
ARRAY_1,
INTEGER_1,
DOUBLE_1
}Type;
typedef struct cjson
{
/*
* 字节对齐稍后再算
*/
struct cjson *next;
struct cjson *prev;
Type t;
char *key;
struct cjson *object; // 对象的首地址
unsigned int object_length;
struct cjson **array; // 数组首地址
unsigned int array_length;
char *string;
long long valueInt;
double valueDouble;
int valueBool;
}Cjson;
/*
* json解析入口,使用完毕请及时释放
*/
Cjson* jsonParser(char *s);
/*
* 创建一个新的cjson节点,并初始化
*/
static Cjson* createNewNode();
/*
* 将数组拆分成二维数组
*/
static unsigned int getRow(char *s);
Cjson **splitArray(char *s, unsigned int *length);
/*
* 在所有键值中寻找key,并返回key所对应的cjson
*/
Cjson *cjson_find(Cjson *root, char *key);
/*
* 假如json 以数组为组成结构,返回第index个数组
*/
Cjson *cjson_fingArray(Cjson *root, int index);
/*
* 计算cjson总长度,由于末尾没有逗号也会被认为有逗号,所以会比原始长度大
*/
static unsigned int cjson_all_length(Cjson *root);
/*
* 将cjson封装字符串
*/
static void packing(Cjson *root, char **buffer, char *numberBuffer);
/*
* 封装入口 cachelength 缓冲内存大小,如果小于零,程序会自行计算大小,使用完毕请及时释放
*/
char *cjson_toString(Cjson *root, unsigned int cacheLength);
/*
* 删除整张或部分表,这取决于root
*/
void free_all_cjson(Cjson *root);
/*
* 1表示删除成功,0表示失败,
*/
int free_cjsonByKey(Cjson *node, char *key);
Cjson *createRoot();
#endif //CJSON_CJSON_H
然后是辅助工具的定义
内存申请工具
#ifndef CJSON_MEMERY_APPLY_H
#define CJSON_MEMERY_APPLY_H
char* createArray(const unsigned int length);
Cjson **createJsonArrayPointer(const unsigned int length);
double* createDouble(const unsigned int length);
long long* createInteger(const unsigned int length);
#endif //CJSON_MEMERY_APPLY_H
计算数字长度
unsigned int getIntegerLength(long long l);
unsigned int getDoubleLength(double d);
json键值的分析工具
#ifndef CJSON_STRING_TOOLS_H
#define CJSON_STRING_TOOLS_H
/*
* 判断类型,分发,返回结果
*/
void parser(char **c_ptr, Type *type, void **content);
static void parseValue(char **value, Type *t, void **content);
static void parseString(char **value, void **content);
static void parseObject(char **value, void **content);
static void parseArray(char **value, void **content);
static void parseBool(char **value, void **content);
#endif //CJSON_STRING_TOOLS_H
下面是代码。
// string_tools.c
//
//
#include "cjson.h"
#include "string_tools.h"
#include "memery_apply.h"
#include <stdlib.h>
#include <stdio.h>
/*
* 截取字符串,判断类型,分发,返回结果
* c_ptr:游标指针
*/
void parser(char **c_ptr, Type *t, void **content)
{
if('"' == **c_ptr)
{
*t = STRING_1;
parseString(c_ptr, content);
}
else if('[' == **c_ptr)
{
*t = ARRAY_1;
parseArray(c_ptr, content);
}
else if('{' == **c_ptr)
{
*t = OBJECT_1;
parseObject(c_ptr, content);
}
else if('t' == **c_ptr || 'f' == **c_ptr)
{
*t = BOOL_1;
parseBool(c_ptr, content);
}
else if(**c_ptr <= '9' && **c_ptr >= '0')
{
parseValue(c_ptr, t, content);
}
}
static void parseValue(char **value, Type *t, void **content)
{
*t = INTEGER_1;
unsigned int content_length = 0;
char *temp = *value;
char *temp1 = *value;
while (*temp != ',' && *temp != ']' && *temp != '}')
{
content_length++;
temp++;
}
temp = createArray(content_length);
int tempCursor = 0;
while (*temp1 != ',' && *temp1 != ']' && *temp1 != '}')
{
if(*temp1 == '.')
{
*t = DOUBLE_1;
}
temp[tempCursor] = *temp1;
temp1++;
tempCursor++;
}
temp[tempCursor] = '\0';
(*value) += content_length;
if(*t == DOUBLE_1)
{
double *i = createDouble(1);
*i = strtod(temp, NULL);
free(temp);
*content = (void*)i;
}
else
{
long long *i = createInteger(1);
*i = strtol(temp, NULL, 10);
free(temp);
*content = (void*)i;
}
}
static void parseString(char **value, void **content)
{
(*value)++;
unsigned int content_length = 0;
char *temp = *value;
char *temp1 = *value;
while (*temp != '"')
{
content_length++;
temp++;
}
// 去掉双引号
temp = createArray(content_length);
int tempCursor = 0;
while (*temp1 != '"')
{
temp[tempCursor] = *temp1;
temp1++;
tempCursor++;
}
(*value) += content_length;
temp[tempCursor] = '\0';
*content = (void*)temp;
(*value)++;
}
static void parseBool(char **value, void **content)
{
unsigned int content_length = 0;
char *temp = *value;
char *temp1 = *value;
while (*temp != ',' && *temp != ']' && *temp != '}')
{
content_length++;
temp++;
}
temp = createArray(content_length);
int tempCursor = 0;
while (*temp1 != ',' && *temp1 != ']' && *temp1 != '}')
{
temp[tempCursor] = *temp1;
temp1++;
tempCursor++;
}
(*value) += content_length;
temp[tempCursor] = '\0';
*content = (void*)temp;
}
static void parseObject(char **value, void **content)
{
unsigned int content_length = 0;
char *temp = *value;
char *temp1 = *value;
int bBrackets = 1;
temp++;
content_length++;
while (1)
{
if('{' != *temp && '}' != *temp)
{
temp++;
content_length++;
continue;
}
if('{' == *temp)
{
temp++;
content_length++;
bBrackets++;
}
if('}' == *temp)
{
temp++;
content_length++;
bBrackets--;
}
if(0 == bBrackets)
{
break;
}
}
temp = createArray(content_length);
int tempCursor = 0;
temp[tempCursor++] = *temp1;
temp1++;
bBrackets = 1;
while (1)
{
if('{' != *temp1 && '}' != *temp1)
{
temp[tempCursor++] = *temp1;
temp1++;
continue;
}
if('{' == *temp1)
{
temp[tempCursor++] = *temp1;
temp1++;
bBrackets++;
}
if('}' == *temp1)
{
temp[tempCursor++] = *temp1;
temp1++;
bBrackets--;
}
if(0 == bBrackets)
{
break;
}
}
(*value) += content_length;
temp[tempCursor] = '\0';
*content = (void*)temp;
}
static void parseArray(char **value, void **content)
{
unsigned int content_length = 0;
char *temp = *value;
char *temp1 = *value;
int mBrackets = 1;
content_length++;
temp++;
while (1)
{
if('[' != *temp && ']' != *temp)
{
temp++;
content_length++;
continue;
}
if('[' == *temp)
{
temp++;
content_length++;
mBrackets++;
}
if(']' == *temp)
{
temp++;
content_length++;
mBrackets--;
}
if(0 == mBrackets)
{
break;
}
}
temp = createArray(content_length);
int tempCursor = 0;
temp[tempCursor++] = *temp1;
temp1++;
mBrackets = 1;
while (1)
{
if('[' != *temp1 && ']' != *temp1)
{
temp[tempCursor++] = *temp1;
temp1++;
continue;
}
if('[' == *temp1)
{
temp[tempCursor++] = *temp1;
temp1++;
mBrackets++;
}
if(']' == *temp1)
{
temp[tempCursor++] = *temp1;
temp1++;
mBrackets--;
}
if(0 == mBrackets)
{
break;
}
}
(*value) += content_length;
temp[tempCursor] = '\0';
*content = (void*)temp;
}
//memery_apply.c
//
//
//
#include <malloc.h>
#include <stdio.h>
#include <mem.h>
#include "cjson.h"
char* createArray(const unsigned int length)
{
char *temp = (char*)malloc(sizeof(char) * (length+1));
if(NULL == temp)
{
printf("申请内存失败,程序异常退出。\n");
exit(-1);
}
memset(temp, 0, sizeof(char) * (length+1));
return temp;
}
Cjson **createJsonArrayPointer(const unsigned int length)
{
Cjson **temp = (Cjson**)malloc(sizeof(Cjson*) * (length));
if(NULL == temp)
{
printf("申请内存失败,程序异常退出。\n");
exit(-1);
}
memset(temp, 0, sizeof(Cjson*) * (length));
return temp;
}
double* createDouble(const unsigned int length)
{
double *temp = (double*)malloc(sizeof(double) * length);
if(NULL == temp)
{
printf("申请内存失败,程序异常退出。\n");
exit(-1);
}
memset(temp, 0, sizeof(int) * length);
return temp;
}
long long* createInteger(const unsigned int length)
{
long long *temp = (long long*)malloc(sizeof(long long) * length);
if(NULL == temp)
{
printf("申请内存失败,程序异常退出。\n");
exit(-1);
}
memset(temp, 0, sizeof(long long) * length);
return temp;
}
// number_tools.c
#define EPS 1e-12
unsigned int getIntegerLength(long long l)
{
long long temp = 10l;
unsigned int len = 1;
while (l/temp != 0)
{
temp = temp * 10l;
len++;
}
return len;
}
unsigned int getDoubleLength(double d)
{
long long high = (long long)d;
double low = d - high;
unsigned int len = getIntegerLength(high);
double temp = low, a = 0.1;
while (low > EPS)
{
low -= a * (long long)(temp * 10l);
a /= 10.0;
temp = temp * 10 - (long long)(temp*10);
len++;
}
return len+1;
}
// cjson.c
//
// Created by admin on 2017/8/13.
//
#include "cjson.h"
#include "string_tools.h"
#include "memery_apply.h"
#include "number_tools.h"
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include <string.h>
#define NUMBER_BUFFER 1024
/*
* 应该提供检查合法性的接口,不然解析中出错返回什么?
*/
Cjson* jsonParser(char *s)
{
// 入口处应加入判断json合法性的选择
Cjson *root = NULL;
Cjson *nowNode = NULL; // 当期节点
if('[' == *s)
{
// 如果直接是数组,直接拆了它
root = createNewNode();
root->t = ARRAY_1;
root->array = splitArray(s, &root->array_length);
return root;
}
if('{' == *s)
{
// 如果是对象
int key_flag = 0;
s++;
while('}' != *s && '\0' != *s)
{
Type t = STRING_1;
void *content;
parser(&s, &t, &content); // 返回的位置一定指向, } ] : 的某一种
if(':' == *s)
{
key_flag = 1;
}
switch (t)
{
case STRING_1:
if(key_flag)
{
// 碰到一个key就新建一个节点,指向当前节点
Cjson *n = createNewNode();
n->key = (char*)content;
// 更新当前节点
if(NULL == nowNode)
{
nowNode = n;
root = nowNode; // 记录首地址
root->object_length++;
}
else
{
nowNode->next = n;
n->prev = nowNode;
nowNode = n;
root->object_length++;
}
}
else
{
nowNode->t = t;
nowNode->string = (char*)content;
}
break;
case OBJECT_1:
nowNode->t = t;
nowNode->object = jsonParser((char*)content); //返回对象首地址
free(content);
break;
case ARRAY_1:
nowNode->t = t;
nowNode->array = splitArray(content, &nowNode->array_length); // 返回二维数组首地址
free(content);
break;
case BOOL_1:
nowNode->t = t;
if(strcmp(content, "true") == 0)
{
nowNode->valueBool = 1;
}
else
{
nowNode->valueBool = 0;
}
free(content);//不能漏掉任何一个堆内存
break;
case INTEGER_1:
nowNode->t = t;
nowNode->valueInt = *(long long*)content;
free(content);
break;
case DOUBLE_1:
nowNode->t = t;
nowNode->valueDouble = *(double*)content;
free(content);
break;
default:
assert(-1);
break;
}
s++;
key_flag = 0;
}
return root;
}
}
static Cjson* createNewNode()
{
Cjson *x = (Cjson*)malloc(sizeof(Cjson));
x->t = STRING_1;
x->object = NULL;
x->string = NULL;
x->next = NULL;
x->prev = NULL;
x->key = NULL;
x->array = NULL;
x->valueBool = 0;
x->valueDouble = 0.0;
x->valueInt = 0l;
x->array_length = 0;
x->object_length = 0;
return x;
}
Cjson **splitArray(char *s, unsigned int *length)
{
if(*s != '[')
{
return NULL;
}
unsigned int i = getRow(s);
*length = i;
Cjson **array = createJsonArrayPointer(i);
Cjson **res = &array[0];
s++;
while (']' != *s && '\0' != *s)
{
void *content = NULL;
Type t = STRING_1;
parser(&s, &t, &content);
*array = createNewNode();
switch (t)
{
case STRING_1:
(*array)->t = STRING_1;
(*array)->string = (char*)content;
break;
case OBJECT_1:
(*array)->t = OBJECT_1;
(*array)->object = jsonParser((char*)content);
free(content);
break;
case ARRAY_1:
(*array)->t =ARRAY_1;
(*array)->array = splitArray((char*)content, &(*array)->array_length);
free(content);
break;
case INTEGER_1:
(*array)->t = INTEGER_1;
(*array)->valueInt = *(long long*)content;
free(content);
break;
case DOUBLE_1:
(*array)->t = DOUBLE_1;
(*array)->valueDouble = *(double*)content;
free(content);
break;
case BOOL_1:
(*array)->t = BOOL_1;
if(strcmp(content, "true") == 0)
{
(*array)->valueBool = 1;
}
else
{
(*array)->valueBool = 0;
}
free(content);
break;
default:
assert(-1);
break;
}
array++;
s++;
}
return res;
}
static unsigned int getRow(char *s)
{
if('[' != *s)
{
return 0;
}
int bBrackets=0,mBrackets=0;
unsigned int rows = 0;
s++;
while ('\0' != *s)
{
if('{' == *s)
{
bBrackets++;
s++;
while (1)
{
if('{' != *s && '}' != *s)
{
s++;
continue;
}
if('{' == *s)
{
s++;
bBrackets++;
}
if('}' == *s)
{
s++;
bBrackets--;
}
if(0 == bBrackets)
{
rows++;
s++; // 直接跳过匹配到的括号
break;
}
}
}
else if('[' == *s)
{
mBrackets++;
s++;
while (1)
{
if('[' != *s && ']' != *s)
{
s++;
continue;
}
if('[' == *s)
{
s++;
mBrackets++;
}
if(']' == *s)
{
s++;
mBrackets--;
}
if(0 == mBrackets)
{
rows++;
s++; // 直接跳过匹配到的括号
break;
}
}
}
else
{
// 数字 字符串 布尔值情况
rows++;
while (',' != *s++);
}
}
return rows;
}
Cjson *cjson_find(Cjson *root, char *key)
{
Cjson *now = root;
while (NULL != now)
{
if(OBJECT_1 == now->t)
{
Cjson *x = cjson_find(now->object, key);
if(NULL != x)
{
return x;
}
}
else if(ARRAY_1 == now->t)
{
Cjson **a = now->array;
unsigned int len = now->array_length;
for (int i = 0; i < len; ++i) {
Cjson *x = cjson_find(a[i], key);
if(NULL != x)
{
return x;
}
}
}
else
{
if(NULL != now->key)
{
if(0 == strcmp(key, now->key))
{
return now;
}
}
}
now = now->next;
}
return NULL;
}
Cjson *cjson_fingArray(Cjson *root, int index)
{
if(ARRAY_1 != root->t)
{
return NULL;
}
Cjson **now = root->array;
int i = 1;
int length = root->array_length;
while (i <= length)
{
if(i == index)
{
return *now;
}
i++;
now++;
}
return NULL;
}
static unsigned int cjson_array_all_length(Cjson *node)
{
unsigned int length = 0;
Cjson *temp;
Cjson **array = node->array;
unsigned int len = node->array_length;
for (int i = 0; i < len; ++i) {
temp = array[i];
length += (cjson_all_length(temp) + 1);
}
return length;
}
static unsigned int cjson_all_length(Cjson *root)
{
// 所求长度大于原长度
unsigned int length = 0;
Cjson *node = root;
while (NULL != node)
{
if(OBJECT_1 == node->t)
{
length += (cjson_all_length(node->object) + 3);
}
else if(ARRAY_1 == node->t)
{
length += (cjson_array_all_length(node) + 3);
}
else
{
if(NULL != node->key)
{
length += (strlen(node->key) + 3);
}
switch (node->t)
{
case INTEGER_1:
length += getIntegerLength(node->valueInt)+2;
break;
case DOUBLE_1:
length += getDoubleLength(node->valueDouble)+2;
break;
case BOOL_1:
if(1 == node->valueBool)
{
length += 5; // true,
}
else
{
length += 6; // false,
}
break;
case STRING_1:
length += (strlen(node->string) + 3);
break;
default:
break;
}
}
node = node->next;
}
return length;
}
static void packing(Cjson *root, char **buffer, char *numberBuffer)
{
Cjson *node = root;
char *cache = *buffer;
while (NULL != node)
{
if(NULL != node->key)
{
*cache = '"';
cache++;
strcat(cache, node->key);
cache += strlen(node->key);
*cache = '"';
cache++;
*cache = ':';
cache++;
}
switch (node->t)
{
case OBJECT_1:
*cache = '{';
cache++;
packing(node->object, &cache, numberBuffer);
*cache = '}';
cache++;
break;
case ARRAY_1:
*cache = '[';
cache++;
unsigned int l = node->array_length;
Cjson *temp;
for (int i = 0; i < l; ++i) {
temp = node->array[i];
packing(temp, &cache, numberBuffer);
}
*cache = ']';
cache++;
break;
case INTEGER_1:
ltoa(node->valueInt, numberBuffer, 10);
strcat(cache, numberBuffer);
cache += strlen(numberBuffer);
break;
case DOUBLE_1:
gcvt(node->valueDouble, 10, numberBuffer);
strcat(cache, numberBuffer);
cache += strlen(numberBuffer);
break;
case BOOL_1:
if(1 == node->valueBool)
{
strcat(cache, "true");
cache += 4;
}
else
{
strcat(cache, "false");
cache += 5;
}
break;
case STRING_1:
*cache = '"';
cache++;
strcat(cache, node->string);
cache += strlen(node->string);
*cache = '"';
cache++;
break;
}
node = node->next;
*cache = ',';
cache++;
}
cache--;
*cache = '\0';
*buffer = cache;
}
char *cjson_toString(Cjson *root, unsigned int cacheLength)
{
if(NULL == root)
{
return "{}";
}
unsigned int length = 0;
if(cacheLength <= 0)
{
length = cjson_all_length(root) + 2;
}
else
{
length = cacheLength;
}
char *result = createArray(length);
char *cache = result;
char *numberBuffer = createArray(NUMBER_BUFFER-1);
packing(root, &cache, numberBuffer);
free(numberBuffer);
return result;
}
static void free_all_cjson_array(Cjson *root)
{
Cjson *node = root;
Cjson *temp;
Cjson **array = node->array;
unsigned int len = node->array_length;
for (int i = 0; i < len; ++i) {
temp = array[i];
free_all_cjson(temp);
}
free(array);
}
void free_all_cjson(Cjson *root)
{
Cjson *node = root;
Cjson *temp;
while (1)
{
if(OBJECT_1 == node->t)
{
free_all_cjson(node->object);
}
if(ARRAY_1 == node->t)
{
free_all_cjson_array(node);
}
if(NULL == node->next)
{
free(node);
break;
}
temp = node;
node = node->next;
free(temp);
}
}
int free_cjsonByKey(Cjson *node, char *key)
{
while (NULL != node)
{
if(NULL != node->key)
{
if(strcmp(key, node->key) == 1)
{
// 删除节点,连接前后节点
return 1;
}
}
node = node->next;
}
return 0;
}
json解析已完毕,封装还有欠缺。
版权声明:本文为nvnnv原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。