以下是一个简单的C语言解析JSON串的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum {
JSON_NULL,
JSON_FALSE,
JSON_TRUE,
JSON_NUMBER,
JSON_STRING,
JSON_ARRAY,
JSON_OBJECT
} json_type;
typedef struct {
json_type type;
union {
double number;
char *string;
struct {
char *start;
size_t size;
} raw;
struct {
struct json_value *values;
size_t count;
} array;
struct {
char **keys;
struct json_value *values;
size_t count;
} object;
} u;
} json_value;
typedef struct {
const char *json;
size_t pos;
} json_context;
static json_value *json_parse_value(json_context *);
static void *json_malloc(size_t size) {
return malloc(size);
}
static void *json_realloc(void *ptr, size_t size) {
return realloc(ptr, size);
}
static void json_free(void *ptr) {
free(ptr);
}
static void json_set_null(json_value *value) {
value->type = JSON_NULL;
}
static void json_set_boolean(json_value *value, int boolean) {
value->type = boolean ? JSON_TRUE : JSON_FALSE;
}
static void json_set_number(json_value *value, double number) {
value->type = JSON_NUMBER;
value->u.number = number;
}
static void json_set_string(json_value *value, const char *string, size_t len) {
value->type = JSON_STRING;
value->u.string = (char *)json_malloc(len + 1);
memcpy(value->u.string, string, len);
value->u.string[len] = '\0';
}
static void json_set_array(json_value *value, size_t count) {
value->type = JSON_ARRAY;
value->u.array.count = count;
value->u.array.values = (json_value *)json_malloc(count * sizeof(json_value));
}
static void json_set_object(json_value *value, size_t count) {
value->type = JSON_OBJECT;
value->u.object.count = count;
value->u.object.keys = (char **)json_malloc(count * sizeof(char *));
value->u.object.values = (json_value *)json_malloc(count * sizeof(json_value));
}
static void json_free_value(json_value *value) {
size_t i;
switch (value->type) {
case JSON_STRING:
json_free(value->u.string);
break;
case JSON_ARRAY:
for (i = 0; i < value->u.array.count; i++)
json_free_value(&value->u.array.values[i]);
json_free(value->u.array.values);
break;
case JSON_OBJECT:
for (i = 0; i < value->u.object.count; i++) {
json_free(value->u.object.keys[i]);
json_free_value(&value->u.object.values[i]);
}
json_free(value->u.object.keys);
json_free(value->u.object.values);
break;
default:
break;
}
value->type = JSON_NULL;
}
static int json_parse_literal(json_context *c, json_value *value, const char *literal, json_type type) {
size_t i;
for (i = 0; literal[i]; i++)
if (c->json[c->pos + i] != literal[i])
return 0;
c->pos += i;
value->type = type;
return 1;
}
static int json_parse_number(json_context *c, json_value *value) {
const char *p = c->json + c->pos;
double n = 0.0, sign = 1.0;
int exp_sign = 1, exp_value = 0;
int i;
if (*p == '-') {
sign = -1.0;
p++;
}
if (*p == '0') {
p++;
} else if (*p >= '1' && *p <= '9') {
do {
n = n * 10.0 + (*p - '0');
p++;
} while (*p >= '0' && *p <= '9');
}
if (*p == '.') {
p++;
if (*p >= '0' && *p <= '9') {
double decimal = 0.0, base = 0.1;
while (*p >= '0' && *p <= '9') {
decimal += (*p - '0') * base;
base *= 0.1;
p++;
}
n += decimal;
} else {
return 0;
}
}
if (*p == 'e' || *p == 'E') {
p++;
if (*p == '-') {
exp_sign = -1;
p++;
} else if (*p == '+') {
p++;
}
if (*p >= '0' && *p <= '9') {
do {
exp_value = exp_value * 10 + (*p - '0');
p++;
} while (*p >= '0' && *p <= '9');
} else {
return 0;
}
}
n *= sign * pow(10.0, exp_sign * exp_value);
value->type = JSON_NUMBER;
value->u.number = n;
c->pos = p - c->json;
return 1;
}
static int json_parse_string(json_context *c, json_value *value) {
const char *p = c->json + c->pos;
char *head, *tail;
size_t len;
int u, u2;
if (*p != '\"')
return 0;
p++;
head = tail = (char *)json_malloc(128);
while (*p != '\"') {
if (*p == '\0') {
json_free(head);
return 0;
}
if (*p != '\\') {
*tail++ = *p++;
} else {
switch (*++p) {
case '\"':
case '\\':
case '/':
*tail++ = *p++;
break;
case 'b':
*tail++ = '\b';
p++;
break;
case 'f':
*tail++ = '\f';
p++;
break;
case 'n':
*tail++ = '\n';
p++;
break;
case 'r':
*tail++ = '\r';
p++;
break;
case 't':
*tail++ = '\t';
p++;
break;
case 'u':
if (!(u = json_parse_hex4(p + 1)))
goto fail;
if (u >= 0xD800 && u <= 0xDBFF) {
if (*(p += 5) != '\\' || *(p + 1) != 'u' || !(u2 = json_parse_hex4(p + 2)))
goto fail;
u = (((u - 0xD800) << 10) | (u2 - 0xDC00)) + 0x10000;
p += 6;
} else {
p += 5;
}
json_encode_utf8(head, &tail, u);
break;
default:
goto fail;
}
}
}
len = tail - head;
json_set_string(value, head, len);
c->pos = p + 1 - c->json;
return 1;
fail:
json_free(head);
return 0;
}
static int json_parse_array(json_context *c, json_value *value) {
size_t size = 0;
json_value element;
int ret;
if (*c->json != '[')
return 0;
c->pos++;
json_parse_whitespace(c);
if (*c->json == ']') {
c->pos++;
json_set_array(value, 0);
return 1;
}
while (1) {
json_init(&element);
if ((ret = json_parse_value(c, &element)) != 1)
break;
memcpy(json_context_push(value, sizeof(json_value)), &element, sizeof(json_value));
size++;
json_parse_whitespace(c);
if (*c->json == ',') {
c->pos++;
json_parse_whitespace(c);
} else if (*c->json == ']') {
c->pos++;
json_set_array(value, size);
value->u.array.count = size;
return 1;
} else {
ret = 0;
break;
}
}
for (size_t i = 0; i < size; i++)
json_free_value(json_context_pop(value, sizeof(json_value)));
return ret;
}
static int json_parse_object(json_context *c, json_value *value) {
size_t size = 0, length;
char *key;
json_value element;
int ret;
if (*c->json != '{')
return 0;
c->pos++;
json_parse_whitespace(c);
if (*c->json == '}') {
c->pos++;
json_set_object(value, 0);
return 1;
}
while (1) {
key = json_parse_string_raw(c, &length);
if (!key) {
ret = 0;
break;
}
json_parse_whitespace(c);
if (*c->json++ != ':') {
json_free(key);
ret = 0;
break;
}
json_parse_whitespace(c);
json_init(&element);
if ((ret = json_parse_value(c, &element)) != 1) {
json_free(key);
break;
}
memcpy(json_context_push(value, sizeof(char *)), &key, sizeof(char *));
memcpy(json_context_push(value, sizeof(json_value)), &element, sizeof(json_value));
size++;
key = NULL;
json_parse_whitespace(c);
if (*c->json == ',') {
c->pos++;
json_parse_whitespace(c);
} else if (*c->json == '}') {
c->pos++;
json_set_object(value, size);
value->u.object.count = size;
return 1;
} else {
ret = 0;
break;
}
}
if (key)
json_free(key);
for (size_t i = 0; i < size; i++) {
json_free(*(char **)json_context_pop(value, sizeof(char *)));
json_free_value(json_context_pop(value, sizeof(json_value)));
}
return ret;
}
static int json_parse_value(json_context *c, json_value *value) {
switch (*c->json) {
case 'n':
return json_parse_literal(c, value, "null", JSON_NULL);
case 't':
return json_parse_literal(c, value, "true", JSON_TRUE);
case 'f':
return json_parse_literal(c, value, "false", JSON_FALSE);
case '\"':
return json_parse_string(c, value);
case '[':
return json_parse_array(c, value);
case '{':
return json_parse_object(c, value);
default:
return json_parse_number(c, value);
}
}
int json_parse(json_value *value, const char *json) {
int ret;
json_context c;
c.json = json;
c.pos = 0;
json_init(value);
json_parse_whitespace(&c);
if ((ret = json_parse_value(&c, value)) == 1) {
json_parse_whitespace(&c);
if (*c.json != '\0') {
value->type = JSON_NULL;
ret = 0;
}
}
return ret;
}
```
这段代码包含了解析JSON中各种数据类型的实现函数,例如 `json_parse_null`、`json_parse_boolean`、`json_parse_number`、`json_parse_string`、`json_parse_array` 和 `json_parse_object`。解析过程中使用了一个结构体 `json_value` 来表示JSON的值,并使用了递归下降的方式来解析。
使用该代码时,只需要调用 `json_parse` 函数并传入待解析的JSON字符串和一个 `json_value` 结构体即可。例如:
```c
#include <stdio.h>
#include "json.h"
int main() {
const char *json_str = "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}";
json_value value;
if (json_parse(&value, json_str)) {
printf("Name: %s\n", json_get_string(&value, "name"));
printf("Age: %d\n", json_get_number(&value, "age"));
printf("City: %s\n", json_get_string(&value, "city"));
} else {
printf("Failed to parse JSON.\n");
}
json_free_value(&value);
return 0;
}
```
这段代码会输出以下结果:
```
Name: John
Age: 30
City: New York
```