来自
从零开始的 JSON 库教程
从零开始教授如何写一个符合标准的 C 语言 JSON 库
作者 Milo Yip
https://zhuanlan.zhihu.com/json-tutorial
根据第一课教程 自己重新编写 做了一点修改 加深学习印象
//JsonParse.h #pragma once #include "JsonStruct.h" #include <assert.h> void DEFParseWhitespace(MyJsonStruct& js) { while (js.jsonStr[js.index] == ' ' || js.jsonStr[js.index] == '\r' || js.jsonStr[js.index] == '\n') { js.index++; } } DefParseResult DEFParseNull(MyJsonStruct& js) { assert(js.jsonStr[js.index] = 'n'); if (js.jsonStr[js.index + 1] != 'u' || js.jsonStr[js.index+2] != 'l' || js.jsonStr[js.index+3] != 'l') { return DEF_PARSE_INVALID_VALUE; } js.index += 4; js.type = DEF_NULL; return DEF_PARSE_OK; } DefParseResult DEFParseValue(MyJsonStruct& js) { switch (js.jsonStr[js.index]){ case 'n':return DEFParseNull(js); case '\0':return DEF_PARSE_EXPECT_VALUE; default:return DEF_PARSE_INVALID_VALUE; } } DefParseType GetParseType(MyJsonStruct& js) { return js.type; } void ResetJsonStruct(const char* jsonBuf, MyJsonStruct& js) { js.jsonStr = jsonBuf; js.index = 0; js.type = DEF_NONE; } MyJsonStruct InitJsonStruct(char* jsonBuf) { MyJsonStruct jsonStruct; ResetJsonStruct(jsonBuf, jsonStruct); return jsonStruct; } DefParseResult DEFParse(MyJsonStruct& jsonStruct) { DefParseResult ret; DEFParseWhitespace(jsonStruct); if ((ret = DEFParseValue(jsonStruct)) == DEF_PARSE_OK) { DEFParseWhitespace(jsonStruct); if (jsonStruct.index < jsonStruct.jsonStr.size()) { ret = DEF_PARSE_ROOT_NOT_SINGULAR; jsonStruct.type = DEF_NONE; } } return ret; }
//JsonStruct.h #pragma once #include <string> enum DefParseType { DEF_NONE, DEF_NULL, DEF_FALSE, DEF_TRUE, DEF_NUMBER, DEF_STRING, DEF_ARRAY, DEF_OBJECT }; struct MyJsonStruct { std::string jsonStr; size_t index; DefParseType type; }; enum DefParseResult{ DEF_PARSE_OK = 0, DEF_PARSE_EXPECT_VALUE, DEF_PARSE_INVALID_VALUE, DEF_PARSE_ROOT_NOT_SINGULAR };
//MyTestUnit.h #pragma once #include <iostream> class MyTestClass { static size_t testCount_; static size_t testPass_; public: template<typename E,typename A> bool ExceptEqual(E e, A a) { testCount_++; if (e == a){ testPass_++; return true; } return false; } void PrintResult(){ std::cout << testPass_ << "/" << testCount_ << "\t" << "("<<(testPass_ * 100.0 / testCount_) << "%)" << " passed." << std::endl; } }; size_t MyTestClass::testCount_ = 0; size_t MyTestClass::testPass_ = 0; #define ERROR_PRINT(expect,actual) \ std::cerr << __FILE__ <<":"<< __LINE__ << "\r\nexpect: " << expect << " actual: " << actual << std::endl; #define EXCEPT_EQ(expect, actual) \ do{ \ MyTestClass TEST; \ if(!TEST.ExceptEqual(expect, actual)){ \ ERROR_PRINT(expect,actual) \ } \ }while(0) #define PRINT_TEST_RESULT() \ do{ \ MyTestClass TEST; \ TEST.PrintResult(); \ }while(0)
// MyJson.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "JsonParse.h" #include <iostream> #include "MyTestUnit.h" int main() { MyJsonStruct js =InitJsonStruct("null"); EXCEPT_EQ(DEF_PARSE_OK, DEFParse(js)); EXCEPT_EQ(DEF_NULL, GetParseType(js)); ResetJsonStruct("", js); EXCEPT_EQ(DEF_PARSE_EXPECT_VALUE, DEFParse(js)); EXCEPT_EQ(DEF_NONE, GetParseType(js)); ResetJsonStruct(" ", js); EXCEPT_EQ(DEF_PARSE_EXPECT_VALUE, DEFParse(js)); EXCEPT_EQ(DEF_NONE, GetParseType(js)); ResetJsonStruct("nul", js); EXCEPT_EQ(DEF_PARSE_INVALID_VALUE, DEFParse(js)); EXCEPT_EQ(DEF_NONE, GetParseType(js)); ResetJsonStruct("?", js); EXCEPT_EQ(DEF_PARSE_INVALID_VALUE, DEFParse(js)); EXCEPT_EQ(DEF_NONE, GetParseType(js)); ResetJsonStruct("null x", js); EXCEPT_EQ(DEF_PARSE_ROOT_NOT_SINGULAR, DEFParse(js)); EXCEPT_EQ(DEF_NONE, GetParseType(js)); PRINT_TEST_RESULT(); return 0; }
测试效果
12/12 (100%) passed.
请按任意键继续. . .