- A minimal Xross-Platform JSON read & write library in C .
- Easy-to-use: it's STL-based, and designed to be used without extra studies.
- Easy-to-assemble: only a tiny header file needs to be included.
- No dependencies: unless STL and std c libraries.
- According to RFC 8259 - The JavaScript Object Notation (JSON) Data Interchange Format.
- Compatiblities:
- Encoding-friendly: support popular encodings, like ASCII, UTF8, GBK, GB2312, BIG 5, UTF16, UTF32, UCS-2, UCS-4.
- OS-friendly: portable for popular platforms, like linux and windows.
- Compiler-friendly: upward support old version of C , and forward support for new features.
- High-performance & high-concurrency aimed.
- 100K scenario validated till now in commercial distributed application service.
- Elegant casting between types, like string to integer, string to float, integer to string, and etc.
- NULL in string value supports.
- Every JSON value occupies fixed 16 bytes size under both 32-bit and 64-bit system.
{
"orca": {
"personalities": {
"age": 28,
"company": "ez8.co",
"gender": "male",
"name": "Zhang Wei"
},
"skills": [
"C ",
"golang",
"python"
]
}
}
- You can rapidly start writing by according to following example.
#include "xpjson.hpp"
#include <iostream>
int main()
{
JSON::Value v;
v["orca"]["personalities"]["age"] = 28;
v["orca"]["personalities"]["name"] = "Zhang Wei";
v["orca"]["personalities"]["gender"] = "male";
v["orca"]["personalities"]["company"] = "ez8.co";
v["orca"]["skills"][0] = "C "; // auto-expand array(for JSON::Value ONLY)
v["orca"]["skills"][1] = "golang";
v["orca"]["skills"][2] = "python";
std::string out;
v.write(out);
std::cout << out << std::endl;
return 0;
}
- The output is :
~$ ./xpjson_example1
{"orca":{"personalities":{"age":28,"company":"ez8.co","gender":"male","name":"Zhang Wei"},"skills":["C ","golang","python"]}}
- But it's not a optimized one compared with the following example.
#include "xpjson.hpp"
#include <iostream>
int main()
{
JSON::Value v;
JSON::Object& orca = v["orca"].o();
JSON::Object& personalities = orca["personalities"].o();
personalities["age"] = 28;
personalities["name"] = "Zhang Wei";
personalities["gender"] = "male";
personalities["company"] = "ez8.co";
JSON::Array& skills = orca["skills"].a();
skills.resize(2);
skills[0] = "C ";
skills[1] = "golang";
// Use JSON_MOVE to gain perf-opt benefits under C 11 if available.
skills.push_back(JSON_MOVE(string("python")));
std::string out;
// reserve 100 bytes, reduce reallocation and copy cost of time
out.reserve(100);
v.write(out);
std::cout << out << std::endl;
return 0;
}
- And you can read the stream by according to following example.
#include "xpjson.hpp"
#include <iostream>
#include <cassert>
int main()
{
std::string in("{\"orca\":{\"personalities\":{\"age\":28,\"company\":\"ez8.co\",\"gender\":\"male\",\"name\":\"Zhang Wei\"},\"skills\":[\"C \",\"golang\",\"python\"]}}");
JSON::Value v;
size_t ret = v.read(in);
assert(ret == in.length());
JSON::Object& orca = v["orca"].o();
assert(orca.size() == 2);
JSON::Object& personalities = orca["personalities"].o();
JSON::Array& skills = orca["skills"].a();
std::cout << "Personalities:" << std::endl;
for(JSON::Object::const_iterator it=personalities.begin(); it!=personalities.end(); it) {
std::string out;
it->second.to_string(out);
std::cout << it->first << " -> " << out << std::endl;
}
std::cout << endl << "Skills:" << std::endl;
for(JSON::Array::const_iterator it=skills.begin(); it!=skills.end(); it) {
std::cout << it->s() << std::endl;
}
return 0;
}
- The output is :
~$ ./xpjson_example3
Personalities:
age -> 28
company -> ez8.co
gender -> male
name -> Zhang Wei
Skills:
C
golang
python
- You MUST catch exception while using following methods that may throw exception.
try {
string in("{}");
JSON::Value v;
v.read(v, in.c_str(), in.length());
}
catch(std::exception &e) {
printf("Error : %s.", e.what());
// or do what you want
}
Class Name | Method Name |
---|---|
JSON::Reader | read |
JSON::Value | read |
JSON::Value | read_nil |
JSON::Value | read_boolean |
JSON::Value | read_number |
JSON::Value | read_string |
JSON::Value | b |
JSON::Value | i |
JSON::Value | f |
JSON::Value | s |
JSON::Value | o |
JSON::Value | a |
- You should care about the life cycle of input string or buffer by yourself when using
COW
feature. - Pass
true
tocow
switch to enableCOW
feature manually. COW
feature may be automatically inherited by assignment or movement or reference.
Class Name | Method Name |
---|---|
JSON::Reader | read |
JSON::Value | read |
JSON::Value | read_nil |
JSON::Value | read_boolean |
JSON::Value | read_number |
JSON::Value | read_string |
JSON::Value | ValueT(string/buffer related) |
JSON::Value | assign(string/buffer related) |
- <UNDER CONSTRUCTION>
- Can skip detection that whether string needs to be encoded or escaped.
- Enable detecttion as default.
- Use a flag to skip when put string.
- Auto set during
read
if skip is possible.
- Invalid after modifications (or possible modifications like get reference operation as memory watch is not ready now).
- Which should not check every character during
write
and may gain SIMD intrinsics benefits of memxxx APIs (about 30% bonous as benchmark said).
- Enable detecttion as default.
- No useless pretty print (indent, CRLF, space and other formats).
- Gaudy feature I think, because performance, size of packet and binaries is most important, not low-frequency debug dump.
- Use online json-validation web or web browser console to show them in pretty formats instead.
- Less extra conditions (about 10% bonous as benchmark said).
- As less temporary variables and condition branches as possible.
- Auto enable move operations if compiler supports to reduce memory copy.
- Scan only once during parse.
- Type-traits for value input and elegant cast between types.
- High-concurrency support. No global mutex lock (compare with bxxst).
- Transfer as-is, as less en(de)coding operations as possible.
- Hardcode en(de)coding, without depends of library like iconv or system APIs.
- SSO(Small-String-Optimization) & COW(Copy-On-Write) support.
- Reader & Writer for file / stream.
- New
readv
method by passing iovec param. - Optimization of using CPU intrinsics set.
- Please feel free to use xpjson.
- Looking forward to your suggestions.
- If your project is using xpjson, you can show your project or company here by creating a issue or let me know.