#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define X64_LONG_MAX 9223372036854775807L
typedef enum json_type_e {
JSON_NUM,
JSON_STRING,
JSON_TRUE,
JSON_FALSE,
JSON_NULL,
JSON_OBJ,
JSON_ARRAY,
} json_type_t;
typedef struct json_value_s json_value_t;
typedef struct json_obj_s json_obj_t;
typedef struct json_array_s json_array_t;
struct json_value_s {
json_type_t type;
union {
json_obj_t *obj;
json_array_t *array;
long num;
char *str;
} val;
struct json_obj_s {
char *key;
json_value_t value;
json_obj_t *next;
struct json_array_s {
json_value_t value;
json_array_t *next;
typedef struct json_ctx_s {
const char *cur;
} json_ctx_t;
int parse_obj(json_ctx_t *ctx, json_value_t *v);
int parse_value(json_ctx_t *ctx, json_value_t *v);
int is_whitespace(char c) {
return c == ' ' || c == '\r' || c == '\n' || c == '\t';
void skip_whitespace(json_ctx_t *ctx) {
while (is_whitespace(*ctx->cur)) {
ctx->cur++;
int parse_string(json_ctx_t *ctx, char **out) {
ctx->cur++;
const char *begin = ctx->cur;
size_t num = 0;
while (*ctx->cur != '"') {
ctx->cur++;
num++;
char *tmp = (char *) malloc(num + 1);
if (tmp == NULL)
return -1;
strncpy(tmp, begin, num);
tmp[num] = '\0';
*out = tmp;
ctx->cur++;
return 0;
int parse_number(json_ctx_t *ctx, json_value_t *v) {
long n = 0;
if (ctx->cur[0] == '0' && ctx->cur[1] != '0' && isdigit(ctx->cur[1]))
return -1;
int sign_flag = 1;
if (*ctx->cur == '-') {
sign_flag = -1;
ctx->cur++;
while (isdigit(*ctx->cur)) {
if (n > X64_LONG_MAX / 10)
return -1;
if (n == X64_LONG_MAX / 10 && *ctx->cur - '0' > X64_LONG_MAX % 10)
return -1;
n = n * 10 + (*ctx->cur) - '0';
ctx->cur++;
v->type = JSON_NUM;
v->val.num = n * sign_flag;
return 0;
int parse_array(json_ctx_t *ctx, json_value_t *v) {
if (*ctx->cur != '[')
return -1;
ctx->cur++;
skip_whitespace(ctx);
if (*ctx->cur == ']')
return 0;
v->type = JSON_ARRAY;
while (1) {
json_array_t *a = malloc(sizeof(json_array_t));
if (a == NULL)
return -1;
a->next = v->val.array;
v->val.array = a;
if (parse_value(ctx, &a->value) != 0)
return -1;
skip_whitespace(ctx);
if (*ctx->cur == ']') {
ctx->cur++;
return 0;
if (*ctx->cur == ',') {
ctx->cur++;
} else {
return -1;
skip_whitespace(ctx);
int parse_obj(json_ctx_t *ctx, json_value_t *v) {
if (*ctx->cur != '{')
return -1;
ctx->cur++;
skip_whitespace(ctx);
if (*ctx->cur == '}')
return 0;
v->type = JSON_OBJ;
while (1) {
json_obj_t *m = malloc(sizeof(json_obj_t));
if (m == NULL)
return -1;
m->next = v->val.obj;
v->val.obj = m;
if (*ctx->cur == '"') {
parse_string(ctx, &m->key);
} else {
return -1;
skip_whitespace(ctx);
if (*ctx->cur++ != ':')
return -1;
skip_whitespace(ctx);
if (parse_value(ctx, &m->value) == -1)
return -1;
skip_whitespace(ctx);
if (*ctx->cur == ',') {
ctx->cur++;
skip_whitespace(ctx);
} else if (*ctx->cur == '}') {
ctx->cur++;
return 0;
} else {
return -1;
int parse_string_word(json_ctx_t *ctx, const char *word, json_value_t *v, json_type_t type) {
while (*word) {
if (*ctx->cur != *word)
return -1;
ctx->cur++;
word++;
v->type = type;
return 0;
int parse_value(json_ctx_t *ctx, json_value_t *v) {
switch (*ctx->cur) {
case '"':
v->type = JSON_STRING;
return parse_string(ctx, &v->val.str);
case '{':
v->type = JSON_OBJ;
v->val.obj = NULL;
return parse_obj(ctx, v);
case 't':
v->type = JSON_TRUE;
return parse_string_word(ctx, "true", v, JSON_TRUE);
case 'f':
v->type = JSON_FALSE;
return parse_string_word(ctx, "false", v, JSON_FALSE);
case 'n':
v->type = JSON_NULL;
return parse_string_word(ctx, "null", v, JSON_NULL);
case '[':
v->type = JSON_ARRAY;
v->val.array = NULL;
return parse_array(ctx, v);
default:
return parse_number(ctx, v);
json_value_t *parse(const char *json) {
json_ctx_t ctx;
ctx.cur = json;
skip_whitespace(&ctx);
if (*ctx.cur != '{')
return NULL;
json_value_t *v = malloc(sizeof(json_value_t));
if (v == NULL)
return NULL;
int ret = parse_value(&ctx, v);
if (ret != 0) {
printf("parse ret %d\n", ret);
return v;
void show(json_value_t *value) {
switch (value->type) {
case JSON_STRING:
printf("[str]%s\n", value->val.str);
break;
case JSON_NUM:
printf("[num]%ld\n", value->val.num);
break;
case JSON_OBJ:
printf("[obj]-----start\n");
json_obj_t *head = value->val.obj;
while (head) {
printf("[key]%s:\t", head->key);
printf("[value]");
show(&head->value);
head = head->next;
printf("[obj]-----end\n");
break;
case JSON_ARRAY:
printf("[array]-----start\n");
json_array_t *arr = value->val.array;
while (arr) {
printf("[value]");
show(&arr->value);
arr = arr->next;
printf("[array]-----end\n");
break;
case JSON_TRUE:
printf("true\n");
break;
case JSON_FALSE:
printf("false\n");
break;
case JSON_NULL:
printf("null\n");
break;
default:
return;
int main() {
char *json = "{\"hi\":[1,\"hi\",{\"hello\":22}],\n"
"\"isNull \":null,\n"
"\"isTrue\": true,\n"
"\"hello2\":-2,\n"
"\"arr2\":[\"hi\",3]}";
json_value_t *value = parse(json);
if (value == NULL) {
printf("parse error!\n");
return -1;
show(value);
return 0;
后面可以进一步扩展 ?
JSON字符串解析利用递归下降非常容易实现。本文实现了一个不支持数组,数字解析只支持正数long类型,只支持ASCII字符集的极简JSON解析器,未实现的功能后面也比较容易扩展。
评分:4.9 | 下载:366,130 | 最新版本:1.5
Plugin地址:Json Parser - IntelliJ IDEs Plugin | Marketplace
2. 推荐理由
JSON作为主流的数据交换格式,在程序里随处可见,例如application/json格式的POST请求、MQ的body。为了排查方便,往往会将这些地方的入参序列化成JSON后打印出来。之后再查看这些参数时,就需要先格式化一下JSON内容,方便我们
正文开始。今天用FastJson的时候遇到一个错误,报错如下:
Exception in thread "main" com.alibaba.fastjson.JSONException: syntax error, expect {, actual ], pos 39
at com.alibaba.
在只有64K甚至只有20K这样KB级别的内存资源极其有限的单片机中,要解析如下这种复杂的多级嵌套结构的json数据是很头疼的事。常用的cJSON解析器是通过链表将json数据按照键值对的形式展开,在解析过程中会大量的动态申请内存。在rtthread操作系统中,每一次malloc都会携带一个控制块,用于对申请内存的管理,在频繁malloc时,控制块的内存占用会比实际要申请得内存要大得多
"u1_cfg": [115200, 8, 1, 0, 1000],
"u2_cfg": [1152
Pineapple Lang是Go编写的简单编程语言演示工具。它包括一个手写的递归下降解析器和一个简单的解释器,尽管该语言甚至不是图灵完备的。但是,此回购协议的主要目的是使编译原理的初学者热身并简单地了解如何构建编程语言。
$cd examples/pineapple/
$go build
$ ./pineapple hello-world.pineapple
pen pineapple apple pen.
可能是其他语言?
不用担心,我们还有其他pinelang-lang工具供您使用:
Python工具,由:
TypeScript工具:
Dart工具, :
Java工具,由:
另一个Java工具,由实现:
Ruby工具,由:
C#工具:
防锈工具,由:
Scala工具,通过实现:
F#工具,由:
introduction
LL handwriting practice recursive descent algorithm sqlite create table statement parser. See Bowen practicing handwriting a SQLite parser
练习手写LL递归下降算法的sqlite create table语句解析器。
详见博文 练手写了个SQLite解析器
Python实现JSON生成器和递归下降解释器
github地址:https://github.com/EStormLynn/Python-JSON-Parser
从零开始写一个JSON的解析器,特征如下:
符合标准的JSON解析器和生成器
手写递归下降的解释器(recursive descent parser)
使用Python语言(2.7)
解释器和生成器少于500行
使用c...
// 如果当前结点没有子结点或者已经访问过了,就可以访问当前结点
if ((curr->left == NULL && curr->right == NULL) ||
(pre != NULL && (pre == curr->left || pre == curr->right))) {
// 访问当前结点
printf("%d ", curr->val);
// 将当前结点从栈中弹出
stk.pop();
// 将当前结点赋值给 pre
pre = curr;
} else {
// 如果当前结点有右子结点,就将右子结点压入栈中
if (curr->right != NULL) stk.push(curr->right);
// 如果当前结点有左子结点,就将左子结点压入栈中
if (curr->left != NULL) stk.push(curr->left);
上述代码实现了对二叉树的非递归后序遍历。在遍历过程中,使用了一个栈来辅助实现非递归遍历。
需要注意的是,在代码中需要判断当前结点是否有子结点以及当前结点的子结点是否已经访问