栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【json-tutorial】第一章学习笔记

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【json-tutorial】第一章学习笔记


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。


intro
  • 本系列博客是关于学习json-tutorial项目的一些感悟

  • 感觉学习此项目对于使用C语言开发一个实际有用的东西很有帮助,而且作者的教导非常详细,代码也很规范,就决定学习一下

  • 此项目是一个从零开始的JSON库教程,难度适合于学习过基本C/C++编程的同学

  • 我的编码环境是GNU/Linux Mint OS,使用gcc编译代码

  • 这篇博客是关于json-tutorial第一章的内容的理解与思考

  • 内容主要偏向于对当时觉得难懂的地方的复盘笔记,而不是一切都很详细的笔记

turtorial01.md 要实现什么
  • 在初次打开教程的时候,真的是满头雾水,即使作者的教程写的十分详细,但还是有种无从下手的感觉,那么关于这个项目,我们到底要实现什么呢?

  • 关于要实现的JSON库,其需要实现三种需求

    1. 把JSON文本解析为一个树状数据结构–(parse)
    2. 提供接口访问该数据结构–(access)
    3. 把数据结构转换成JSON文本–(stringify)
  • 主目标已经确定,显然很复杂,但是第一章的目标其实很简单,只需要实现对null与boolean的解析即可

要怎么实现
  • 为了实现对null与boolean的解析,我们需要:
    • 在leptjson.h中定义后续所需的结构与函数签名
    • 在leptjson.c中实现解析器
    • 在test.c中实现一个针对该需求的单元测试
  • 其实需要coding的地方就这三处,三个文件中两个实现需求,一个保证需求正常实现,总体框架并不复杂
比较难懂的地方
  • 在第一章中理解作者所提供的宏是一个小小的难点,这个宏很简单,但是如果之前没有接触过比较长宏的话还是比较难懂,我们主要需要去理解它的嵌套
  • 需要理解如果程序在断言(assert)处崩溃是因为程序员的code存在问题
SHOW ME THE CODE
  • 此处的代码都是实现任务目标后的代码
  • 代码才是此项目最核心的部分,让我们来为代码加上详细的注释吧!
  • 此项目采用C89,所以注释部分只能使用
leptjson.h
#ifndef LEPTJSON_H__
#define LEPTJSON_H__


typedef enum { LEPT_NULL, LEPT_FALSE, LEPT_TRUE, LEPT_NUMBER, LEPT_STRING, LEPT_ARRAY, LEPT_OBJECT } lept_type;


typedef struct {
    lept_type type;
}lept_value;


enum {
    LEPT_PARSE_OK = 0,
    LEPT_PARSE_EXPECT_VALUE, 
    LEPT_PARSE_INVALID_VALUE, 
    LEPT_PARSE_ROOT_NOT_SINGULAR
};


int lept_parse(lept_value* v, const char* json);


lept_type lept_get_type(const lept_value* v);

#endif 
leptjson.c
  • .c的文件较长,我们分开来看
宏与结构体
  • 宏
#define EXPECT(c, ch)       do { assert(*c->json == (ch)); c->json++; } while(0)
  • 这个宏就很简单,就是为了断言函数传进来的参数是我们想要的,如果在此处崩溃,则说明coding时调用了错误的API

  • 结构体

typedef struct {
    const char* json;
}lept_context;
  • 将JSON信息放到一个结构体里,主要是为了避免后续解析函数之间传递多个参数
解析器 lept_parse
  • 传入实际想要比较的字符(v) 和 标准字符(json)
int lept_parse(lept_value* v, const char* json) {
    

    
    lept_context c;
    int ret;
    
    assert(v != NULL);
    c.json = json;
    
    v->type = LEPT_NULL;
    
    lept_parse_whitespace(&c);
    if((ret = lept_parse_value(&c, v)) == LEPT_PARSE_OK){
        lept_parse_whitespace(&c);
        if(*c.json != ''){
            ret = LEPT_PARSE_ROOT_NOT_SINGULAR;
        }
    }

    return ret;
}
lept_parse_value
static int lept_parse_value(lept_context* c, lept_value* v) {
    
    switch (*c->json) {
        case 'n':  return lept_parse_null(c, v);
        case 'f':  return lept_parse_false(c, v);
        case 't':  return lept_parse_true(c, v);
        case '': return LEPT_PARSE_EXPECT_VALUE;
        default:   return LEPT_PARSE_INVALID_VALUE;
    }
}
lept_get_type
  • 只要v是一个有意义值,就返回v的类型
lept_type lept_get_type(const lept_value* v) {
    assert(v != NULL);
    
    return v->type;
}
剩余函数
  • 剩余的函数都很容易理解,都是被分别调用执行单个解析任务
test.c
  • 一个简单的测试单元,能够提供测试点测试我们的代码是否可以完成目标需求
宏
  • 测试单元的宏是第一章的一个小难点,其实只需要理解在C语言中的作用以及两个宏之间的所属关系就可以很好的理解这个宏了,而且可以感受到宏的方便之处~~(宏魔法)~~
static int main_ret = 0;
static int test_count = 0;
static int test_pass = 0;

#define EXPECT_EQ_BASE(equality, expect, actual, format) 
    do {
         
        test_count++;
        if (equality)
         
            test_pass++;
        else {
         
            fprintf(stderr, "%s:%d: expect: " format " actual: " format "n", __FILE__, __LINE__, expect, actual);
            main_ret = 1;
        }
    } while(0)


#define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d")
test_parse()
static void test_parse() {
    test_parse_null();
    test_parse_true();
    test_parse_false();
    test_parse_expect_value();
    test_parse_invalid_value();
    test_parse_root_not_singular();
}
demo
static int lept_parse_true(lept_context* c, lept_value* v) {
    
    EXPECT(c, 't');
    
    if (c->json[0] != 'r' || c->json[1] != 'u' || c->json[2] != 'e')
        return LEPT_PARSE_INVALID_VALUE;
    c->json += 3;
    v->type = LEPT_TRUE;
    return LEPT_PARSE_OK;
}

  • 第一章的实现到这里就结束了,都是一些很基础的内容,但果然还是写出来才能感觉更通透一点
参考
  • 从零开始的 JSON 库教程
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/997048.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号