# yyjson clone **Repository Path**: WN90/yyjson-clone ## Basic Information - **Project Name**: yyjson clone - **Description**: clone from https://github.com/ibireme/yyjson/ - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2022-01-14 - **Last Updated**: 2023-01-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # yyjson [![Build](https://img.shields.io/github/workflow/status/ibireme/yyjson/cmake?style=flat-square)](https://github.com/ibireme/yyjson/actions) [![Codecov](https://img.shields.io/codecov/c/gh/ibireme/yyjson?style=flat-square)](https://codecov.io/gh/ibireme/yyjson) [![License](https://img.shields.io/github/license/ibireme/yyjson?color=blue&style=flat-square)](https://github.com/ibireme/yyjson/blob/master/LICENSE) [![Version](https://img.shields.io/github/v/release/ibireme/yyjson?color=orange&style=flat-square)](https://github.com/ibireme/yyjson/releases) A high performance JSON library written in ANSI C. # Features - **Fast**: can read or write gigabytes per second JSON data on modern CPU. - **Portable**: compliance with ANSI C (C89). - **Standard**: strict compliance with [RFC 8259](https://tools.ietf.org/html/rfc8259) and [ECMA-404](https://www.ecma-international.org/publications/standards/Ecma-404.htm) standard. - **Safe**: complete JSON form, number format and UTF-8 validation. - **Accuracy**: can read and write `int64`, `uint64` and `double` number accurately. - **No Limit**: support unlimited JSON level, `\u0000` string. - **Extendable**: options to allow comments, trailing commas, nan/inf, custom memory allocator. - **Developer Friendly**: only one `h` and one `c` file, easy to use API. # Limitations - An array or object is stored as some [data structure](https://github.com/ibireme/yyjson/blob/master/doc/DataStructure.md) like linked list, access elements with index or key is slower than iterator. - Duplicate keys are allowed in an object, and the order of the keys is preserved. - JSON parsing result is immutable, a `mutable copy` is required for modification. # Performance Benchmark project and dataset: [yyjson_benchmark](https://github.com/ibireme/yyjson_benchmark) The simdjson's new `On Demand` API is faster if most JSON fields is known at compile time. This benchmark project only checks the DOM API, new benchmark will be added later. #### AWS EC2 (AMD EPYC 7R32, gcc 9.3) ![ec2_chart](doc/images/perf_reader_ec2.svg) |twitter.json|parse (GB/s)|stringify (GB/s)| |---|---|---| |yyjson(insitu)|1.80|1.51| |yyjson|1.72|1.42| |simdjson|1.52|0.61| |sajson|1.16| | |rapidjson(insitu)|0.77| | |rapidjson(utf8)|0.26|0.39| |cjson|0.32|0.17| |jansson|0.05|0.11| #### iPhone (Apple A14, clang 12) ![a14_chart](doc/images/perf_reader_a14.svg) |twitter.json|parse (GB/s)|stringify (GB/s)| |---|---|---| |yyjson(insitu)|3.51|2.41| |yyjson|2.39|2.01| |simdjson|2.19|0.80| |sajson|1.74|| |rapidjson(insitu)|0.75| | |rapidjson(utf8)|0.30|0.58| |cjson|0.48|0.33| |jansson|0.09|0.24| More benchmark reports with interactive charts (update 2020-12-12) |Platform|CPU|Compiler|OS|Report| |---|---|---|---|---| |Intel NUC 8i5|Core i5-8259U|msvc 2019|Windows 10 2004|[Charts](https://ibireme.github.io/yyjson_benchmark/reports/Intel_NUC_8i5_msvc_2019.html)| |Intel NUC 8i5|Core i5-8259U|clang 10.0|Ubuntu 20.04|[Charts](https://ibireme.github.io/yyjson_benchmark/reports/Intel_NUC_8i5_clang_10.html)| |Intel NUC 8i5|Core i5-8259U|gcc 9.3|Ubuntu 20.04|[Charts](https://ibireme.github.io/yyjson_benchmark/reports/Intel_NUC_8i5_gcc_9.html)| |AWS EC2 c5a.large|AMD EPYC 7R32|gcc 9.3|Ubuntu 20.04|[Charts](https://ibireme.github.io/yyjson_benchmark/reports/EC2_c5a.large_gcc_9.html)| |AWS EC2 t4g.medium|Graviton2 (ARM64)|gcc 9.3|Ubuntu 20.04|[Charts](https://ibireme.github.io/yyjson_benchmark/reports/EC2_t4g.medium_gcc_9.html)| |Apple iPhone 12 Pro|A14 (ARM64)|clang 12.0|iOS 14|[Charts](https://ibireme.github.io/yyjson_benchmark/reports/Apple_A14_clang_12.html)| ### For better performance, yyjson prefers: * A modern processor with: * high instruction level parallelism * excellent branch predictor * low penalty for misaligned memory access * A modern compiler with good optimization. # Building ### Manually Just copy `yyjson.h` and `yyjson.c` to your project and start using it. Since `yyjson` is ANSI C compatible, no other configuration is needed typically. `yyjson` has been tested with the following compilers: `gcc`, `clang`, `msvc`, `icc`, `tcc`. If you find a compile error, please [report a bug](https://github.com/ibireme/yyjson/issues/new?template=bug_report.md). `yyjson` includes all features by default, but you can trim out some of them by adding compile flags to get higher performance and/or smaller binary. See [compile flags](https://github.com/ibireme/yyjson/blob/master/doc/Building.md#compile-flags) for details. ### CMake Clone repository and create build directory: ```shell git clone https://github.com/ibireme/yyjson.git mkdir build cd build ``` Build static library: ```shell cmake .. cmake --build . ``` Build static library and run tests: ```shell cmake .. -DYYJSON_BUILD_TESTS=ON cmake --build . ctest ``` Supported CMake options: - `-DBUILD_SHARED_LIBS=ON` Build shared library instead of static library. - `-DYYJSON_BUILD_TESTS=ON` Build all tests. - `-DYYJSON_DISABLE_READER=ON` Disable JSON reader if you don't need it. - `-DYYJSON_DISABLE_WRITER=ON` Disable JSON writer if you don't need it. - `-DYYJSON_DISABLE_FAST_FP_CONV=ON` Disable fast floating-point number conversion. - `-DYYJSON_DISABLE_NON_STANDARD=ON` Disable non-standard JSON support at compile time. See [compile flags](https://github.com/ibireme/yyjson/blob/master/doc/Building.md#compile-flags) for details. # Sample Code ### Read JSON string ```c const char *json = "{\"name\":\"Mash\",\"star\":4,\"hits\":[2,2,1,3]}"; // Read JSON and get root yyjson_doc *doc = yyjson_read(json, strlen(json), 0); yyjson_val *root = yyjson_doc_get_root(doc); // Get root["name"] yyjson_val *name = yyjson_obj_get(root, "name"); printf("name: %s\n", yyjson_get_str(name)); printf("name length:%d\n", (int)yyjson_get_len(name)); // Get root["star"] yyjson_val *star = yyjson_obj_get(root, "star"); printf("star: %d\n", (int)yyjson_get_int(star)); // Get root["hits"], iterate over the array yyjson_val *hits = yyjson_obj_get(root, "hits"); size_t idx, max; yyjson_val *hit; yyjson_arr_foreach(hits, idx, max, hit) { printf("hit%d: %d\n", (int)idx, (int)yyjson_get_int(hit)); } // Free the doc yyjson_doc_free(doc); // All functions accept NULL input, and return NULL on error. ``` ### Write JSON string ```c // Create a mutable doc yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL); yyjson_mut_val *root = yyjson_mut_obj(doc); yyjson_mut_doc_set_root(doc, root); // Set root["name"] and root["star"] yyjson_mut_obj_add_str(doc, root, "name", "Mash"); yyjson_mut_obj_add_int(doc, root, "star", 4); // Set root["hits"] with an array int hits_arr[] = {2, 2, 1, 3}; yyjson_mut_val *hits = yyjson_mut_arr_with_sint32(doc, hits_arr, 4); yyjson_mut_obj_add_val(doc, root, "hits", hits); // To string, minified const char *json = yyjson_mut_write(doc, 0, NULL); if (json) { printf("json: %s\n", json); // {"name":"Mash","star":4,"hits":[2,2,1,3]} free((void *)json); } // Free the doc yyjson_mut_doc_free(doc); ``` ### Read JSON file with options ```c // Read JSON file, allowing comments and trailing commas yyjson_read_flag flg = YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS; yyjson_read_err err; yyjson_doc *doc = yyjson_read_file("/tmp/config.json", flg, NULL, &err); // Iterate over the root object if (doc) { yyjson_val *obj = yyjson_doc_get_root(doc); yyjson_obj_iter iter; yyjson_obj_iter_init(obj, &iter); yyjson_val *key, *val; while ((key = yyjson_obj_iter_next(&iter))) { val = yyjson_obj_iter_get_val(key); printf("%s: %s\n", yyjson_get_str(key), yyjson_get_type_desc(val)); } } else { printf("read error (%u): %s at position: %ld\n", err.code, err.msg, err.pos); } // Free the doc yyjson_doc_free(doc); ``` ### Write JSON file with options ```c // Read the JSON file as a mutable doc yyjson_mut_doc *doc = yyjson_mut_read_file("/tmp/config.json", 0, NULL, NULL); yyjson_mut_val *obj = yyjson_mut_doc_get_root(doc); // Remove null values in root object yyjson_mut_obj_iter iter; yyjson_mut_obj_iter_init(obj, &iter); yyjson_mut_val *key, *val; while ((key = yyjson_mut_obj_iter_next(&iter))) { val = yyjson_mut_obj_iter_get_val(key); if (yyjson_mut_is_null(val)) { yyjson_mut_obj_iter_remove(&iter); } } // Write the json pretty, escape unicode yyjson_write_flag flg = YYJSON_WRITE_PRETTY | YYJSON_WRITE_ESCAPE_UNICODE; yyjson_write_err err; yyjson_mut_write_file("/tmp/config.json", doc, flg, NULL, &err); if (err.code) { printf("write error (%u): %s\n", err.code, err.msg); } // Free the doc yyjson_mut_doc_free(doc); ``` # Documentation * [Building](https://github.com/ibireme/yyjson/blob/master/doc/Building.md) * [API and sample code](https://github.com/ibireme/yyjson/blob/master/doc/API.md) * [Data structure](https://github.com/ibireme/yyjson/blob/master/doc/DataStructure.md) # TODO * [x] Add documentation page. * [x] Add GitHub workflow for CI and codecov. * [x] Add more tests: valgrind, sanitizer. * [x] Support JSON Pointer to query value from document. * [ ] Add fuzzer. * [ ] Add `RAW` type for JSON reader and writer. * [ ] Add streaming API for JSON reader and writer. * [ ] Add documentation about performance. * [ ] Optimize performance for 32-bit processor. # License This project is released under the MIT license.