这节介绍如何根据json对象生产json字符串: 如{“a”:1}到“{\“a\”:1}”。
leptjson.cpp
生成空和布尔类型json值, 直接添加
case LEPT_NULL: PUTS(c, "null", 4); break;
case LEPT_FALSE: PUTS(c, "false", 5); break;
case LEPT_TRUE: PUTS(c, "true", 4); break;
生成数据类型json值, 有三种方法
本质上都是, 将数字通过sprintf函数转化为字符串, 然后将字符串添加到栈上。
sprintf函数会返回数字转换的字符串长度。
case LEPT_NUMBER:
{
/*char buffer[32];
int length = sprintf(buffer, "%.17g", v->u.n);
PUTS(c, buffer, length);
break;*/
c->top -= 32 - sprintf((char*)lept_context_push(c, 32), "%.17g", v->u.n);
break;
/*char* buffer = (char*)lept_context_push(c, 32);
int length = sprintf(buffer, "%.17g", v->u.n);
c->top -= 32 - length;
break;*/
}
生成字符串类型的json值。
主要处理转义字符和ASCII前20位
// Unoptimized
//static void lept_stringify_string(lept_context* c, const char* s, size_t len) {
// size_t i;
// assert(s != NULL);
// PUTC(c, '"');
// for (i = 0; i < len; i++) {
// unsigned char ch = (unsigned char)s[i];
// switch (ch) {
// case '\"': PUTS(c, "\\\"", 2); break;
// case '\\': PUTS(c, "\\\\", 2); break;
// case '\b': PUTS(c, "\\b", 2); break;
// case '\f': PUTS(c, "\\f", 2); break;
// case '\n': PUTS(c, "\\n", 2); break;
// case '\r': PUTS(c, "\\r", 2); break;
// case '\t': PUTS(c, "\\t", 2); break;
// default:
// if (ch < 0x20) {
// char buffer[7];
// sprintf_s(buffer, ch, "\\u%04X"); // ?
// PUTS(c, buffer, 6);
// }
// else
// PUTC(c, s[i]);
// }
// }
// PUTC(c, '"');
//}
static void lept_stringify_string(lept_context* c, const char* s, size_t len) {
static const char hex_digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
size_t i, size;
char* head, * p;
assert(s != NULL);
p = head = (char*)lept_context_push(c, size = len * 6 + 2); /* "\u00xx..." */
*p++ = '"';
for (i = 0; i < len; i++) {
unsigned char ch = (unsigned char)s[i];
switch (ch) {
case '\"': *p++ = '\\'; *p++ = '\"'; break;
case '\\': *p++ = '\\'; *p++ = '\\'; break;
case '\b': *p++ = '\\'; *p++ = 'b'; break;
case '\f': *p++ = '\\'; *p++ = 'f'; break;
case '\n': *p++ = '\\'; *p++ = 'n'; break;
case '\r': *p++ = '\\'; *p++ = 'r'; break;
case '\t': *p++ = '\\'; *p++ = 't'; break;
default:
if (ch < 0x20) {
*p++ = '\\'; *p++ = 'u'; *p++ = '0'; *p++ = '0';
*p++ = hex_digits[ch >> 4];
*p++ = hex_digits[ch & 15];
}
else
*p++ = s[i];
}
}
*p++ = '"';
c->top -= size - (p - head);
}
生产数组和对象。
根据size数据循环添加
case LEPT_ARRAY:
PUTC(c, '[');
for (i = 0; i < v->u.a.size; i++) {
if (i > 0)
PUTC(c, ',');
lept_stringify_value(c, &v->u.a.e[i]);
}
PUTC(c, ']');
break;
case LEPT_OBJECT:
PUTC(c, '{');
for (i = 0; i < v->u.o.size; i++) {
if (i > 0)
PUTC(c, ',');
lept_stringify_string(c, v->u.o.m[i].k, v->u.o.m[i].klen);
PUTC(c, ':');
lept_stringify_value(c, &v->u.o.m[i].v);
}
PUTC(c, '}');
break;
test.cpp
// 往返测试
#define TEST_ROUNDTRIP(json)\
do{\
lept_value v;\
char* json2;\
size_t length;\
lept_init(&v);\
EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, json));\
json2 = lept_stringify(&v,&length);\
/*printf("_________%s\n",json2);\*/\
EXPECT_EQ_STRING(json, json2, length);\
lept_free(&v);\
free(json2);\
}while(0)