# JSON
* Milo Yip
* 2016/10/7
[ JSON ](https://zhuanlan.zhihu.com/json-tutorial) [json-tutorial/tutorial05](https://github.com/miloyip/json-tutorial/blob/master/tutorial05)
1. [JSON ](#1-json-)
2. [](#2-)
3. [](#3-)
4. [](#4-)
5. [](#5-)
## 1. JSON
JSON JSON nested JSON
~~~
array = %x5B ws [ value *( ws %x2C ws value ) ] ws %x5D
~~~
`%x5B` `[``%x2C` `,``%x5D` `]` `ws` `[]``[1,2,true]``[[1,2],[3,4],"abc"]` JSON `[1,2,]` C/C++JavascriptJavaC#
JSON
## 2.
JSON
JSON C $O(1)$ cache coherence JSON
linked list $O(n)$ cache miss
JSON JSON
`lept_value` `union`
~~~c
typedef struct lept_value lept_value;
struct lept_value {
union {
struct { lept_value* e; size_t size; }a; /* array */
struct { char* s; size_t len; }s;
double n;
}u;
lept_type type;
};
~~~
`lept_value` forward declare
`size` API JSON
~~~c
size_t lept_get_array_size(const lept_value* v) {
assert(v != NULL && v->type == LEPT_ARRAY);
return v->u.a.size;
}
lept_value* lept_get_array_element(const lept_value* v, size_t index) {
assert(v != NULL && v->type == LEPT_ARRAY);
assert(index < v->u.a.size);
return &v->u.a.e[index];
}
~~~
API
~~~c
#if defined(_MSC_VER)
#define EXPECT_EQ_SIZE_T(expect, actual) EXPECT_EQ_BASE((expect) == (actual), (size_t)expect, (size_t)actual, "%Iu")
#else
#define EXPECT_EQ_SIZE_T(expect, actual) EXPECT_EQ_BASE((expect) == (actual), (size_t)expect, (size_t)actual, "%zu")
#endif
static void test_parse_array() {
lept_value v;
lept_init(&v);
EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "[ ]"));
EXPECT_EQ_INT(LEPT_ARRAY, lept_get_type(&v));
EXPECT_EQ_SIZE_T(0, lept_get_array_size(&v));
lept_free(&v);
}
~~~
C `size_t` `lept_get_array_size()` `EXPECT_EQ_SIZE_T`ANSI CC89 `size_t` C99 `"%zu"` VS2015 VC `"%Iu"` VC ANSI C
## 3.
JSON
JSON
JSON JSON JSON
`["abc",[1,2],3]`
`[` `lept_parse_array()`

`lept_value` `lept_parse_value()` `"` `lept_parse_string()`

`lept_parse_string()` `"`

`lept_parse_string()` 3

`lept_parse_array()`

`[` `lept_parse_array()` `lept_parse_number()`


`]` 2


`]` 3

## 4.
`lept_parse_array()`
~~~c
static int lept_parse_value(lept_context* c, lept_value* v); /* */
static int lept_parse_array(lept_context* c, lept_value* v) {
size_t size = 0;
int ret;
EXPECT(c, '[');
if (*c->json == ']') {
c->json++;
v->type = LEPT_ARRAY;
v->u.a.size = 0;
v->u.a.e = NULL;
return LEPT_PARSE_OK;
}
for (;;) {
lept_value e;
lept_init(&e);
if ((ret = lept_parse_value(c, &e)) != LEPT_PARSE_OK)
return ret;
memcpy(lept_context_push(c, sizeof(lept_value)), &e, sizeof(lept_value));
size++;
if (*c->json == ',')
c->json++;
else if (*c->json == ']') {
c->json++;
v->type = LEPT_ARRAY;
v->u.a.size = size;
size *= sizeof(lept_value);
memcpy(v->u.a.e = (lept_value*)malloc(size), lept_context_pop(c, size), size);
return LEPT_PARSE_OK;
}
else
return LEPT_PARSE_MISS_COMMA_OR_SQUARE_BRACKET;
}
}
static int lept_parse_value(lept_context* c, lept_value* v) {
switch (*c->json) {
/* ... */
case '[': return lept_parse_array(c, v);
}
}
~~~
`lept_value e` `lept_parse_value()` `]`
`lept_parse_value()` `lept_parse_array()` `lept_parse_array()` `lept_parse_value()`
bug `memcpy()` `lept_parse_value`
~~~c
for (;;) {
/* bug! */
lept_value* e = lept_context_push(c, sizeof(lept_value));
lept_init(e);
size++;
if ((ret = lept_parse_value(c, e)) != LEPT_PARSE_OK)
return ret;
/* ... */
}
~~~
bug 5
## 5.
1. `test_parse_array()` 2 JSON API
~~~js
[ null , false , true , 123 , "abc" ]
[ [ ] , [ 0 ] , [ 0 , 1 ] , [ 0 , 1 , 2 ] ]
~~~
2. `lept_parse_array()` `lept_parse_whitespace()`
3. [](../tutorial03_answer/tutorial03_answer.md) `lept_parse_array()` `malloc()` `free()`
4. test.c `#if 0 ... #endif` `lept_parse_array()` `Assertion failed: (c.top == 0)` `lept_parse_array()`
5. 4 bug
[issue](https://github.com/miloyip/json-tutorial/issues)