[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/zhangyuke-coder/json-tutorial/master/tutorial05/tutorial05.md [Back]  [Original]

#  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()`

![ ](images/parse_array01.png)

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

![ ](images/parse_array02.png)

 `lept_parse_string()`  `"`

![ ](images/parse_array03.png)

 `lept_parse_string()`  3 

![ ](images/parse_array04.png)

 `lept_parse_array()`

![ ](images/parse_array05.png)

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

![ ](images/parse_array06.png)



![ ](images/parse_array07.png)

 `]` 2 

![ ](images/parse_array08.png)



![ ](images/parse_array09.png)

 `]` 3 

![ ](images/parse_array10.png)

## 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) 

Web Proxy Viewer  |  New URL  |  Original Page