请自行约束两种语言数据结构语法上的不同,避开如下问题:

1、json本身不约束key是否符合一个编程语言中的变量名,所以编写用于和编程语言数据结构交互的json代码时应该注意key是否正确。

2、lua没有数组,利用哈希表实现的逻辑上的数组,在中间可以存在不连续的情况时json将无法识别。

3、lua的字符串key可以和数字key共存,这对于json来说,是不允许的。

这些代码我已经用了很久了,所以暂时不多解释了,依赖c++11以上的版本,

代码挺多,有需求可以直接复制,这么多代码的目的也就是更高性能,单纯的在C++里面跑,比谷歌的实现稍微快一点点。

好了,废话不多说,上代码

#pragma once
#include <string>
#include <functional>
#include <setjmp.h>
#include <fstream>
#include <vector> namespace aqx { #ifndef jsize_t
typedef unsigned int jsize_t;
#endif #ifndef jnumber_t
typedef double jnumber_t;
#endif static short constexpr jsvt_null{ 0 };
static short constexpr jsvt_string{ 1 };
static short constexpr jsvt_number{ 2 };
static short constexpr jsvt_boolean{ 3 };
static short constexpr jsvt_object{ 4 };
static short constexpr jsvt_group{ 5 }; namespace aqx_internal {
#ifndef __AQX_UTF8_CHAR_LEN
#define __AQX_UTF8_CHAR_LEN
static unsigned char utf8_char_len[] = {
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
};
#endif static unsigned int json_char_state[] = {
0,0,0,0,0,0,0,0,0,32,96,0,0,96,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
32,0,640,0,0,0,0,0,0,0,0,1048576,65536,8192,131072,512,
3072,3072,3072,3072,3072,3072,3072,3072,3072,3072,16,0,0,0,0,0,
0,1024,1024,1024,1024,5120,1024,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,4,768,8,0,0,
0,17408,1024,1024,1024,21504,50176,0,0,0,0,0,278528,0,524800,0,
0,0,16896,16384,49664,279040,0,0,0,0,0,1,0,2,0,0
}; static int u16c2u8c(unsigned long u16c, unsigned char *u8c) {
if (u16c <= 0x0000007F) {
u8c[0] = u16c & 0x7F;
return 1;
}
else if (u16c >= 0x00000080 && u16c <= 0x000007FF) {
u8c[1] = (u16c & 0x3F) | 0x80;
u8c[0] = ((u16c >> 6) & 0x1F) | 0xC0;
return 2;
}
else if (u16c >= 0x00000800 && u16c <= 0x0000FFFF)
{
u8c[2] = (u16c & 0x3F) | 0x80;
u8c[1] = ((u16c >> 6) & 0x3F) | 0x80;
u8c[0] = ((u16c >> 12) & 0x0F) | 0xE0;
return 3;
}
else if (u16c >= 0x00010000 && u16c <= 0x001FFFFF)
{
u8c[3] = (u16c & 0x3F) | 0x80;
u8c[2] = ((u16c >> 6) & 0x3F) | 0x80;
u8c[1] = ((u16c >> 12) & 0x3F) | 0x80;
u8c[0] = ((u16c >> 18) & 0x07) | 0xF0;
return 4;
}
else if (u16c >= 0x00200000 && u16c <= 0x03FFFFFF)
{
u8c[4] = (u16c & 0x3F) | 0x80;
u8c[3] = ((u16c >> 6) & 0x3F) | 0x80;
u8c[2] = ((u16c >> 12) & 0x3F) | 0x80;
u8c[1] = ((u16c >> 18) & 0x3F) | 0x80;
u8c[0] = ((u16c >> 24) & 0x03) | 0xF8;
return 5;
}
else if (u16c >= 0x04000000 && u16c <= 0x7FFFFFFF)
{
u8c[5] = (u16c & 0x3F) | 0x80;
u8c[4] = ((u16c >> 6) & 0x3F) | 0x80;
u8c[3] = ((u16c >> 12) & 0x3F) | 0x80;
u8c[2] = ((u16c >> 18) & 0x3F) | 0x80;
u8c[1] = ((u16c >> 24) & 0x3F) | 0x80;
u8c[0] = ((u16c >> 30) & 0x01) | 0xFC;
return 6;
} return 0;
} namespace JSON_SYNTAX {
static constexpr auto _T_OBJECT_BEGIN{ static_cast<unsigned int>(0x01) }; // {
static constexpr auto _T_OBJECT_END{ static_cast<unsigned int>(0x02) }; // }
static constexpr auto _T_GROUP_BEGIN{ static_cast<unsigned int>(0x04) }; // [
static constexpr auto _T_GROUP_END{ static_cast<unsigned int>(0x08) }; // ]
static constexpr auto _T_VALUE{ static_cast<unsigned int>(0x10) }; // :
static constexpr auto _T_SPACE{ static_cast<unsigned int>(0x20) }; // 4个空白字符" \t\r\n"
static constexpr auto _T_ENDL{ static_cast<unsigned int>(0x40) }; // 2个换行符"\r\n"
static constexpr auto _T_TEXT{ static_cast<unsigned int>(0x80) }; // "
static constexpr auto _T_ESCAPE_BEGIN{ static_cast<unsigned int>(0x100) }; // 转义符开始 '\\'
static constexpr auto _T_ESCAPE_TYPE{ static_cast<unsigned int>(0x200) }; // 转义符类型 "nrtbfu\\"
static constexpr auto _T_HEX{ static_cast<unsigned int>(0x400) }; // \u之后UTF16的4字符HEX,"abcdefABCDEF"
static constexpr auto _T_NUMBER{ static_cast<unsigned int>(0x800) }; // 数字"0-9"
static constexpr auto _T_E{ static_cast<unsigned int>(0x1000) }; // 科学计数法 e或E
static constexpr auto _T_NEGATIVE{ static_cast<unsigned int>(0x2000) }; // 负数 -
static constexpr auto _T_BOOL{ static_cast<unsigned int>(0x4000) }; // true false
static constexpr auto _T_BOOL_BEGIN{ static_cast<unsigned int>(0x8000) }; // t f
static constexpr auto _T_NEXT{ static_cast<unsigned int>(0x10000) }; // ,
static constexpr auto _T_DECIMAL{ static_cast<unsigned int>(0x20000) }; // 小数点 .
static constexpr auto _T_NULL{ static_cast<unsigned int>(0x40000) }; // null
static constexpr auto _T_NULL_BEGIN{ static_cast<unsigned int>(0x80000) }; // n
static constexpr auto _T_POSITIVE{ static_cast<unsigned int>(0x100000) }; // +
} static constexpr auto _jnf{ static_cast<jsize_t>(-1) }; template<typename _Ty> class _json_parser; class _jts_base {
public:
_jts_base() {
text = nullptr;
} void init(const char *_Text, int _Size) {
text = _Text;
size = _Size;
instr = false;
flags = 0;
index = 0;
} jsize_t open_instr() {
instr = true;
jsize_t _Result = flags;
flags = 0;
return _Result;
} void close_instr(jsize_t _Flags) {
instr = false;
flags = _Flags;
} jsize_t set_flags(jsize_t _Flags) {
auto _Result = flags;
flags = _Flags;
return _Result;
} long subhextol(int left, int len) {
long _Result = 0;
int rlen = len;
for (int i = 0; i < len; i++) {
char c = text[--rlen];
long _Tmp;
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
_Tmp = c - '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
_Tmp = c - 'a' + 10;
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
_Tmp = c - 'A' + 10;
break;
default:
return 0;
}
_Result += (_Tmp << (i << 2));
}
return _Result;
} protected:
const char *text;
jsize_t size;
unsigned int s;
char c;
unsigned char cl;
bool instr;
unsigned int flags;
jsize_t index;
std::string tmp;
}; class _jts_utf8 : public _jts_base
{
public:
int operator++() { c = text[index];
cl = utf8_char_len[(unsigned char)c];
if (cl != 1) {
if (flags == JSON_SYNTAX::_T_ESCAPE_TYPE || !instr)
return -1;
do {
index += cl;
c = text[index];
cl = utf8_char_len[(unsigned char)c];
} while (cl != 1);
}
s = json_char_state[c];
if (flags & s) {
index += cl;
return 0;
} if (instr) {
if (s & JSON_SYNTAX::_T_ENDL)
return -1; index += cl;
return 0;
} return -1;
} private:
friend class _json_parser<_jts_utf8>;
}; class _jts_gbk : public _jts_base
{
public:
int operator++() {
c = text[index];
cl = ((unsigned char)c & 0x80) ? 2 : 1;
if (cl != 1) {
if (flags == JSON_SYNTAX::_T_ESCAPE_TYPE || !instr)
return -1;
do {
index += cl;
c = text[index];
cl = ((unsigned char)c & 0x80) ? 2 : 1;
} while (cl != 1);
}
s = json_char_state[c];
if (flags & s) {
index += cl;
return 0;
} if (instr) {
if (s & JSON_SYNTAX::_T_ENDL)
return -1; index += cl;
return 0;
} return -1;
} private:
friend class _json_parser<_jts_gbk>;
}; class _json_tree {
public:
class node {
public:
node() {
_Size = 0;
_Bgn = _Parent = _jnf;
} node(jsize_t _Pa) {
_Size = 0;
_Parent = _Pa;
_Bgn = _jnf;
} jsize_t size() {
return _Size;
} jsize_t begin() {
return _Bgn;
} private:
friend class _json_parser<_jts_utf8>;
friend class _json_parser<_jts_gbk>;
friend class _json_tree;
jsize_t _Size, _Bgn, _End, _Parent;
}; class var {
public: var() {
Key = _jnf;
Next = _jnf;
Kty = 1;
Type = 0;
} var(short _KTy, jsize_t _Key) {
Next = _jnf;
Kty = _KTy;
Key = _Key;
Type = 0;
} var(short _KTy, jsize_t _Key, short _Type, jsize_t _Val) {
Next = _jnf;
Kty = _KTy;
Key = _Key;
Type = _Type;
Off = _Val;
} var(short _KTy, jsize_t _Key, short _Type, bool _Val) {
Next = _jnf;
Kty = _KTy;
Key = _Key;
Type = _Type;
Stat = _Val;
} var(short _KTy, jsize_t _Key, short _Type, jnumber_t _Val) {
Next = _jnf;
Kty = _KTy;
Key = _Key;
Type = _Type;
Number = _Val;
} short type() { return Type; }
bool is_ikey() { return Kty == 1; }
var *next(_json_tree &_Tree) {
if (Next == _jnf)
return nullptr;
return _Tree.get_val(Next);
} jsize_t ikey() {
return (is_ikey()) ? Key : _jnf;
} const char *skey(_json_tree &_Tree) {
return (!is_ikey()) ? _Tree.get_text(Key) : "";
} bool toboolean() {
return Stat;
} const char *tostring(_json_tree &_Tree) {
return (type() == 1) ? _Tree.get_text(Off) : "";
} jnumber_t tonumber() {
return (type() == 2) ? Number : 0;
} node *toobject(_json_tree &_Tree) {
return (type() == aqx::jsvt_object || type() == aqx::jsvt_group) ? _Tree.get_node(Off) : nullptr;
} private:
friend class _json_parser<_jts_utf8>;
friend class _json_parser<_jts_gbk>;
friend class _json_tree;
jsize_t Key;
jsize_t Next;
short Type;
short Kty;
union {
bool Stat;
jsize_t Off;
jnumber_t Number;
};
}; _json_tree() {
_Texts = { 0, 0, 0 };
} node *get_root() {
if (_Nodes.size() < 2)return nullptr;
return get_node(1);
} var *get_root_val() {
if (_Nodes.size() < 2)return nullptr;
return get_val(1);
} node *get_node(jsize_t _Ref) { return (_Ref < (jsize_t)_Nodes.size()) ? &(_Nodes[_Ref]) : nullptr; }
var *get_val(jsize_t _Ref) { return (_Ref < (jsize_t)_Vals.size()) ? &(_Vals[_Ref]) : nullptr; }
const char *get_text(jsize_t _Ref) { return (_Ref <= _Texts.size) ? _Texts.data + _Ref : nullptr; } void reserve(jsize_t _TextSize, jsize_t _Count) {
if (_TextSize << 1 > _Texts.capacity)
_Realloc_Texts(_TextSize << 1);
_Vals.reserve(_Count << 1);
_Nodes.reserve(_Count);
} void clear() {
_Texts.size = 0;
_Vals.clear();
_Nodes.clear();
} private:
void _set_child(node *e, jsize_t v) {
if (e->_Bgn == _jnf) {
e->_Bgn = v;
e->_End = v;
}
else {
get_val(e->_End)->Next = v;
e->_End = v;
}
} jsize_t new_node(jsize_t _Node, jsize_t &_Name, short _Type) {
jsize_t _Result = (jsize_t)_Nodes.size();
_Nodes.push_back(node(_Node));
jsize_t v = (jsize_t)_Vals.size();
auto e = get_node(_Node);
if (_Name != _jnf) {
_Vals.push_back(var(0, _Name, _Type, _Result));
_Name = _jnf;
e->_Size++;
}
else
_Vals.push_back(var(1, e->_Size++, _Type, _Result));
_set_child(e, v);
return _Result;
} jsize_t new_root() {
jsize_t _Result = (jsize_t)_Nodes.size();
_Nodes.push_back(node());
jsize_t v = (jsize_t)_Vals.size();
_Vals.push_back(var(1, _jnf, aqx::jsvt_object, _Result));
return _Result;
} void _Realloc_Texts(jsize_t _NewCapacity = 0) {
if (_NewCapacity != 0)
_Texts.capacity = (_NewCapacity + (_NewCapacity >> 1));
else
_Texts.capacity = (_Texts.capacity + (_Texts.capacity >> 1));
if (_Texts.capacity < 0x1000)
_Texts.capacity = 0x1000;
char *_Tmp = new char[_Texts.capacity];
if (_Texts.data) {
if (_Texts.size)
memcpy_s(_Tmp, _Texts.capacity, _Texts.data, _Texts.size);
delete _Texts.data;
}
_Texts.data = _Tmp;
} jsize_t new_text(const char *_Text, int _Len) {
jsize_t x = _Texts.size + (sizeof(size_t) - (_Texts.size % sizeof(size_t)));
if (x + _Len >= _Texts.capacity)
_Realloc_Texts(x + _Len);
char *_Target = _Texts.data + x;
_Texts.size = x + (_Len--);
memcpy_s(_Target, _Len, _Text, _Len);
_Target[_Len] = 0;
return x;
} void append_text(const char *_Text, int _Len) {
if (_Texts.size + _Len >= _Texts.capacity)
_Realloc_Texts(_Texts.size + _Len);
char *_Target = _Texts.data + _Texts.size - 1;
_Texts.size += _Len--;
_Texts.size--;
memcpy_s(_Target, _Len, _Text, _Len);
_Target[_Len] = 0;
} void append_char(char _Chr) {
if (_Texts.size + 1 >= _Texts.capacity)
_Realloc_Texts(_Texts.size + 1);
_Texts.data[_Texts.size - 1] = _Chr;
_Texts.data[_Texts.size++] = 0;
} void back_text(int _Len) {
_Texts.size -= _Len;
_Texts.data[_Texts.size] = 0;
} jsize_t new_var_string(jsize_t _Node, jsize_t &_Name, jsize_t _Text) {
jsize_t v = (jsize_t)_Vals.size();
auto e = get_node(_Node);
if (_Name != _jnf) {
_Vals.push_back(var(0, _Name, aqx::jsvt_string, _Text));
_Name = _jnf;
e->_Size++;
}
else
_Vals.push_back(var(1, e->_Size++, aqx::jsvt_string, _Text));
_set_child(e, v);
return v;
} jsize_t new_var_number(jsize_t _Node, jsize_t &_Name, jnumber_t _Number) {
jsize_t v = (jsize_t)_Vals.size();
auto e = get_node(_Node);
if (_Name != _jnf) {
_Vals.push_back(var(0, _Name, aqx::jsvt_number, _Number));
_Name = _jnf;
e->_Size++;
}
else
_Vals.push_back(var(1, e->_Size++, aqx::jsvt_number, _Number));
_set_child(e, v);
return v;
} jsize_t new_var_boolean(jsize_t _Node, jsize_t &_Name, bool _Stat) {
jsize_t v = (jsize_t)_Vals.size();
auto e = get_node(_Node);
if (_Name != _jnf) {
_Vals.push_back(var(0, _Name, aqx::jsvt_boolean, _Stat));
_Name = _jnf;
e->_Size++;
}
else
_Vals.push_back(var(1, e->_Size++, aqx::jsvt_boolean, _Stat));
_set_child(e, v);
return v;
} jsize_t new_var_null(jsize_t _Node, jsize_t &_Name) {
jsize_t v = (jsize_t)_Vals.size();
auto e = get_node(_Node);
if (_Name != _jnf) {
_Vals.push_back(var(0, _Name, aqx::jsvt_null, (jnumber_t)0));
_Name = _jnf;
e->_Size++;
}
else
_Vals.push_back(var(1, e->_Size++, aqx::jsvt_null, (jnumber_t)0));
_set_child(e, v);
return v;
} private:
friend class _json_parser<_jts_utf8>;
friend class _json_parser<_jts_gbk>;
std::vector<var> _Vals;
std::vector<node> _Nodes;
struct _TEXTS_POOL { char *data; jsize_t size; jsize_t capacity; }_Texts;
}; template<typename _Ty>
class _json_parser {
public:
_json_parser(_json_tree &_Tree) {
tree = &_Tree;
} bool load_string(const char *_Text, jsize_t _Len = _jnf, bool _MultiRoot = false) {
if ((int)_Len < 0)
_Len = (jsize_t)strlen(_Text) + 1;
jts.init(_Text, _Len);
tree->clear();
return j_root(_MultiRoot) == 0;
} bool load_file(const std::string _File, bool _MultiRoot = false) {
std::ifstream f(_File.c_str(), std::ifstream::binary);
if (!f)
return false;
f.seekg(0, f.end);
size_t fs = (size_t)f.tellg();
f.seekg(0, f.beg);
char *_Buf = new char[fs + 2];
_Buf[fs] = 0;
_Buf[fs + 1] = 0;
f.read(_Buf, fs);
f.close();
bool _Result = load_string(_Buf, (jsize_t)fs, _MultiRoot);
delete _Buf;
return _Result;
} jsize_t get_error_pos() { /*for (int i = err_pos; i < err_pos + 10; i++)
printf("%c", jts.text[i]);
printf("\n");*/
return err_pos;
} private:
void jtsnext() {
if ((jts.index >= jts.size) || (++jts) != 0) {
err_pos = jts.index;
longjmp(_Rem, -1);
}
} void j_ec(jsize_t &_Off, jsize_t &_TextOff) {
jsize_t len = jts.index - _Off;
if (_TextOff == (jsize_t)-1)
_TextOff = tree->new_text(jts.text + _Off, len);
else
tree->append_text(jts.text + _Off, len); jts.close_instr(JSON_SYNTAX::_T_ESCAPE_TYPE);
jtsnext();
if (jts.c == 'u') {
jsize_t ecpos = jts.index;
unsigned long _uc1 = 0;
int _uc1_len = 0;
char u8c[7];
for (;;) {
jts.set_flags(JSON_SYNTAX::_T_HEX);
for (int i = 0; i < 4; i++) {
jtsnext();
} unsigned long uc = (unsigned short)jts.subhextol(ecpos, jts.index - ecpos);
if (_uc1 >= 0xD800 && _uc1 < 0xDBFF && uc >= 0xDC00 && uc < 0xDFFF) {
int u8l = u16c2u8c((_uc1 - 0xD800) * 0x400 + (uc - 0xDC00) + 0x10000, (unsigned char*)u8c);
u8c[u8l] = 0;
tree->back_text(_uc1_len + 1);
tree->append_text(u8c, u8l + 1);
_uc1 = 0;
}
else {
_uc1 = uc;
_uc1_len = u16c2u8c(uc, (unsigned char*)u8c);
u8c[_uc1_len] = 0;
tree->append_text(u8c, _uc1_len + 1);
} jts.open_instr();
if (jts.c != '\\') {
_Off = jts.index;
jts.index--;
break;
} jts.close_instr(JSON_SYNTAX::_T_ESCAPE_TYPE);
jtsnext();
if (jts.c != 'u') {
_Off = jts.index - 1;
jts.index -= 2;
break;
}
}
}
else {
switch (jts.c)
{
case '\\':
tree->append_char('\\');
break;
case 'n':
tree->append_char('\n');
break;
case 'r':
tree->append_char('\r');
break;
case 't':
tree->append_char('\t');
break;
case 'b':
tree->append_char('\b');
break;
case 'f':
tree->append_char('\f');
break;
case '/':
tree->append_char('/');
break;
} _Off = jts.index;
} jts.open_instr(); //继续放飞自我
} void j_text(bool isname = false) {
jsize_t pos = jts.index;
auto f = jts.open_instr();//字符串里的东西就开始放飞自我了,允许所有,除了不能换行
jsize_t text_off = (jsize_t)-1;
jsize_t text_len = 0; for (;;)
{
jtsnext();
if (jts.c == '\\') {
j_ec(pos, text_off);
}
else if (jts.c == '"') {
break;
}
} jts.close_instr(f);
jsize_t len = jts.index - pos;
if (text_off == (jsize_t)-1)
text_off = tree->new_text(jts.text + pos, len);
else
tree->append_text(jts.text + pos, len); if (isname)
name_off = text_off;
else
tree->new_var_string(cur, name_off, text_off);
} void j_number() {
//考虑到可能会传入常量字符串到json解析,所以,在不拷贝源字符串,不能修改源字符串的情况下,只有自己实现数字转换的代码,这里统一使用浮点类型进行计算 /*
有一点没有遵循标准,标准对于数字前的多个0是不允许的,
但是它允许了-0 -0.00000000000 0e00000000000 之类的这些同样无意义的东西存在
而我没有判断这一点,因为我觉得这会带来额外的性能损失,也会使这段代码变得更为复杂,
我认为这一点,不管这些无意义的0在哪,由程序员自行控制它,
只约束头部,不管中间,尾巴的做法,除了降低性能,没有什么实际意义。
*/
unsigned int myf;
long double _Number = 0;
long double factor;
bool neg = false;
if (jts.c == '-') {
neg = true;
jts.set_flags(JSON_SYNTAX::_T_NUMBER);
jtsnext();
myf = JSON_SYNTAX::_T_NUMBER | JSON_SYNTAX::_T_E | JSON_SYNTAX::_T_DECIMAL |
JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_OBJECT_END | JSON_SYNTAX::_T_GROUP_END | JSON_SYNTAX::_T_NEXT;
jts.set_flags(myf);
}
else
{
myf = JSON_SYNTAX::_T_NUMBER | JSON_SYNTAX::_T_E | JSON_SYNTAX::_T_DECIMAL |
JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_OBJECT_END | JSON_SYNTAX::_T_GROUP_END | JSON_SYNTAX::_T_NEXT;
jts.set_flags(myf);
} do { //整数部分
_Number = _Number * 10 + (jts.c - '0');
jtsnext();
} while (jts.s & JSON_SYNTAX::_T_NUMBER); if (jts.c == '.') {
//小数点之后的数字
factor = 1.0;
jts.set_flags(JSON_SYNTAX::_T_NUMBER);
jtsnext();
myf ^= JSON_SYNTAX::_T_DECIMAL;//之后不再允许小数点
jts.set_flags(myf); do {
factor *= 0.1;
_Number += (jts.c - '0') * factor;
jtsnext();
} while (jts.s & JSON_SYNTAX::_T_NUMBER);
} if ((jts.c | 32) == 'e') {
//科学计数的处理
unsigned int expo = 0;//指数
factor = 10.0;//因数
//e之后,必须是+-或者数字,如果是+-,那么后面必须是一个数字
//这里是json唯一允许+号出现的地方
jts.set_flags(JSON_SYNTAX::_T_NUMBER | JSON_SYNTAX::_T_NEGATIVE | JSON_SYNTAX::_T_POSITIVE);
jtsnext();
if (jts.c == '-') {
jts.set_flags(JSON_SYNTAX::_T_NUMBER);
jtsnext();
factor = 0.1;
}
else if (jts.c == '+') {
jts.set_flags(JSON_SYNTAX::_T_NUMBER);
jtsnext();
} jts.set_flags(JSON_SYNTAX::_T_NUMBER |
JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_OBJECT_END | JSON_SYNTAX::_T_GROUP_END | JSON_SYNTAX::_T_NEXT);
do {
expo = 10 * expo + (jts.c - '0');
jtsnext();
} while (jts.s & JSON_SYNTAX::_T_NUMBER); for (;;) {
//根据指数计算因数的快速求幂的方法
if (expo & 1)
_Number *= factor;
if ((expo >>= 1) == 0)
break;
factor *= factor;
}
} if (!(jts.s & JSON_SYNTAX::_T_SPACE))//非空白字符时,倒退到上一个字符,由此处判断一下会由微小的性能提升,毕竟一次jtsnext()的代价更高一些
--jts.index;
tree->new_var_number(cur, name_off, (jnumber_t)(neg ? -_Number : _Number));
} void j_true() {
jts.set_flags(JSON_SYNTAX::_T_BOOL);
for (int i = 0; i < 3; i++) {
jtsnext();
if ("rue"[i] != jts.c) {
err_pos = jts.index - 1;
longjmp(_Rem, -1);
}
}
tree->new_var_boolean(cur, name_off, true);
} void j_false() {
jts.set_flags(JSON_SYNTAX::_T_BOOL);
for (int i = 0; i < 4; i++) {
jtsnext();
if ("alse"[i] != jts.c) {
err_pos = jts.index - 1;
longjmp(_Rem, -1);
}
}
tree->new_var_boolean(cur, name_off, false);
} void j_null() {
jts.set_flags(JSON_SYNTAX::_T_NULL);
for (int i = 0; i < 3; i++) {
jtsnext();
if ("ull"[i] != jts.c) {
err_pos = jts.index - 1;
longjmp(_Rem, -1);
}
}
tree->new_var_null(cur, name_off);
} void j_value() {
jts.set_flags(
JSON_SYNTAX::_T_SPACE | // 空白字符
JSON_SYNTAX::_T_TEXT | // "
JSON_SYNTAX::_T_OBJECT_BEGIN | // {
JSON_SYNTAX::_T_GROUP_BEGIN | // [
JSON_SYNTAX::_T_NUMBER | // 0-9
JSON_SYNTAX::_T_NEGATIVE | // -负号
JSON_SYNTAX::_T_BOOL_BEGIN | // true false开头
JSON_SYNTAX::_T_NULL_BEGIN
); bool ok = false;
do { jtsnext(); } while (jts.s & JSON_SYNTAX::_T_SPACE); switch (jts.c) {
case '"':
j_text();
break;
case '{':
j_object();
break;
case '[':
j_group();
break;
case '-':
j_number();
break;
case 't':
j_true();
break;
case 'f':
j_false();
break;
case 'n':
j_null();
break;
default:
if (jts.s & JSON_SYNTAX::_T_NUMBER) {
j_number();
break;
}
break;
}
} void j_group() {
// [ 之后,允许空白字符,"{0-9] true false null
auto f = jts.set_flags(
JSON_SYNTAX::_T_SPACE | // 空白字符
JSON_SYNTAX::_T_TEXT | // "
JSON_SYNTAX::_T_OBJECT_BEGIN | // {
JSON_SYNTAX::_T_GROUP_END | // ]
JSON_SYNTAX::_T_NUMBER | // 0-9
JSON_SYNTAX::_T_NEGATIVE | // -负号
JSON_SYNTAX::_T_BOOL_BEGIN | // t f
JSON_SYNTAX::_T_NULL_BEGIN | // n
JSON_SYNTAX::_T_GROUP_BEGIN // 在遇到[时就递归前进
); auto _Node = cur;
cur = tree->new_node(cur, name_off, aqx::jsvt_group);
bool ok = false; do {
jtsnext(); switch (jts.c) {
case '"':
j_text();
jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
break;
case '{':
j_object();
jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
break;
case '[':
j_group();
jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
break;
case '-':
j_number();
jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
break;
case 't':
j_true();
jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
break;
case 'f':
j_false();
jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
break;
case 'n':
j_null();
jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
break;
case ']':
ok = true;
break;
case ',':
jts.set_flags(
JSON_SYNTAX::_T_SPACE | // 空白字符
JSON_SYNTAX::_T_TEXT | // "
JSON_SYNTAX::_T_OBJECT_BEGIN | // {
JSON_SYNTAX::_T_NUMBER | // 0-9
JSON_SYNTAX::_T_NEGATIVE | // -负号
JSON_SYNTAX::_T_BOOL_BEGIN | // t f
JSON_SYNTAX::_T_NULL_BEGIN | // n
JSON_SYNTAX::_T_GROUP_BEGIN // 在遇到[时就递归前进
);
break;
default:
if (jts.s & JSON_SYNTAX::_T_NUMBER) {
j_number();
break;
}
break;
}
} while (!ok); jts.set_flags(f);
cur = _Node;
} void j_object() {
auto _Node = cur;
cur = tree->new_node(cur, name_off, aqx::jsvt_object);
auto f = jts.set_flags(JSON_SYNTAX::_T_TEXT | JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_OBJECT_END);
bool ok = false;
do {
jtsnext();
switch (jts.c) {
case '"':
j_text(true);
//名称字符串结束后,只允许 : 和 空白字符
jts.set_flags(JSON_SYNTAX::_T_VALUE | JSON_SYNTAX::_T_SPACE);
break;
case ':':
j_value();
jts.set_flags(JSON_SYNTAX::_T_TEXT | JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_OBJECT_END | JSON_SYNTAX::_T_NEXT);
break;
case ',':
// 碰到逗号时,新的一轮开始,但此时不再允许花括号,也就是不允许{"a":1,}这样的
jts.set_flags(JSON_SYNTAX::_T_TEXT | JSON_SYNTAX::_T_SPACE);
break;
case '}':
ok = true;
break;
}
} while (!ok);
cur = _Node;
} int j_root(bool _MultiRoot) {
if (setjmp(_Rem)) {
tree->clear();
return -1;
} root = tree->new_root();
cur = root;
name_off = _jnf;
err_pos = 0;
jts.set_flags(JSON_SYNTAX::_T_OBJECT_BEGIN | JSON_SYNTAX::_T_GROUP_BEGIN | JSON_SYNTAX::_T_SPACE);
for (;;) {
jtsnext();
if (jts.c == '{') {
j_object();
break;
}
else if (jts.c == '[') {
j_group();
break;
}
} if (!_MultiRoot) {
jts.open_instr();
for (;;) {
if (jts.index >= jts.size)
break; char _Chr = jts.text[jts.index++];
if (!_Chr)
break; if (!(json_char_state[(unsigned char)_Chr] & JSON_SYNTAX::_T_SPACE)) {
err_pos = jts.index - 1;
//tree->clear();
return -1;
}
}
}
return 0;
} private:
jmp_buf _Rem;
_Ty jts;
_json_tree *tree;
jsize_t cur;
jsize_t root;
jsize_t name_off;
jsize_t err_pos;
}; } using json_tree = aqx_internal::_json_tree; template<typename _Ty>
using json_parser_t = aqx_internal::_json_parser<_Ty>; using jts_gbk = aqx_internal::_jts_gbk;
using jts_utf8 = aqx_internal::_jts_utf8; } /* //我已经把代码移植到C去了,最终我还是又回到C++来使用它,因为。。。C的性能,反而不如C++,无论是vc还是gcc都是不如c++...
//可能的原因是我对C的二进制优化的手法并不纯熟而导致的问题,完全照搬结构大概是不合理的做法,
//不过我认为更多的可能性还是,C入栈的参数比C++要多而导致的。
//毕竟,this指针总在cx si之间传,而C,要写入太多太多结构指针 //下面这一串是构建字符状态表的代码 int sztext[128];
memset(sztext, 0, 512); sztext['\"'] = aqx::aqx_internal::JSON_SYNTAX::_T_TEXT | aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
sztext[':'] = aqx::aqx_internal::JSON_SYNTAX::_T_VALUE;
sztext[','] = aqx::aqx_internal::JSON_SYNTAX::_T_NEXT;
sztext['{'] = aqx::aqx_internal::JSON_SYNTAX::_T_OBJECT_BEGIN;
sztext['}'] = aqx::aqx_internal::JSON_SYNTAX::_T_OBJECT_END;
sztext['['] = aqx::aqx_internal::JSON_SYNTAX::_T_GROUP_BEGIN;
sztext[']'] = aqx::aqx_internal::JSON_SYNTAX::_T_GROUP_END;
sztext['\\'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_BEGIN | aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
sztext['n'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
sztext['r'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
sztext['t'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
sztext['b'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
sztext['f'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
sztext['u'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
sztext['/'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
sztext['\n'] = aqx::aqx_internal::JSON_SYNTAX::_T_ENDL | aqx::aqx_internal::JSON_SYNTAX::_T_SPACE;
sztext['\r'] = aqx::aqx_internal::JSON_SYNTAX::_T_ENDL | aqx::aqx_internal::JSON_SYNTAX::_T_SPACE;
sztext[' '] = aqx::aqx_internal::JSON_SYNTAX::_T_SPACE;
sztext['\t'] = aqx::aqx_internal::JSON_SYNTAX::_T_SPACE; for (size_t i = 0; i < strlen("0123456789"); i++)
sztext["0123456789"[i]] = aqx::aqx_internal::JSON_SYNTAX::_T_NUMBER | aqx::aqx_internal::JSON_SYNTAX::_T_HEX;
for (size_t i = 0; i < strlen("abcdefABCDEF"); i++)
sztext["abcdefABCDEF"[i]] = aqx::aqx_internal::JSON_SYNTAX::_T_HEX; sztext['.'] = aqx::aqx_internal::JSON_SYNTAX::_T_DECIMAL; sztext['+'] = aqx::aqx_internal::JSON_SYNTAX::_T_POSITIVE;
sztext['-'] = aqx::aqx_internal::JSON_SYNTAX::_T_NEGATIVE;
sztext['e'] |= aqx::aqx_internal::JSON_SYNTAX::_T_E;
sztext['E'] |= aqx::aqx_internal::JSON_SYNTAX::_T_E; sztext['t'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
sztext['t'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL_BEGIN;
sztext['r'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
sztext['u'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
sztext['e'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
sztext['f'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
sztext['f'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL_BEGIN;
sztext['a'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
sztext['l'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
sztext['s'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL; sztext['n'] |= aqx::aqx_internal::JSON_SYNTAX::_T_NULL_BEGIN;
sztext['u'] |= aqx::aqx_internal::JSON_SYNTAX::_T_NULL;
sztext['l'] |= aqx::aqx_internal::JSON_SYNTAX::_T_NULL;
for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 16; x++)
{
printf("%d,", sztext[y * 16 + x]);
} printf("\n");
} return 0; */

封装给lua使用的库:

//ljsonlib.h
#pragma once
#include "lua/lua.hpp"
#include "aqx/json.h" class ljson_convert {
public:
ljson_convert(lua_State *_s, int ec);
int table_to_json(int n);
int json_to_table(const char *_Text, int _Len); private:
friend int lua_table_to_json(lua_State *s);
void json_to_object(aqx::jsize_t _Ref);
void json_to_group(aqx::jsize_t _Ref);
int ec_mode;
aqx::json_tree jt;
aqx::json_parser_t<aqx::jts_gbk> *pgbk;
aqx::json_parser_t<aqx::jts_utf8> *putf8;
lua_State *s;
std::string b;
}; //_CharEncoding为字符编码格式,默认为"gbk",可以传入"utf8"
ljson_convert *lua_openljsonlib(lua_State *s, const char *_CharEncoding = "");
//ljsonlib.cpp
#include "pch.h"
#include "ljsonlib.h" #define lua_isintnum(_Number_) (_Number_ - floor(_Number_) < 1e-6) ljson_convert::ljson_convert(lua_State *_s, int ec) {
s = _s;
jt.reserve(0x1000, 0x400);
b.reserve(0x1000);
ec_mode = ec;
if (!ec_mode)
pgbk = new aqx::json_parser_t<aqx::jts_gbk>(jt);
else
putf8 = new aqx::json_parser_t<aqx::jts_utf8>(jt);
} int ljson_convert::table_to_json(int n) {
char sznum[128];
lua_pushnil(s);
int t = 0;
if (!lua_next(s, n))
return 0; switch (lua_type(s, -2)) {
case LUA_TNUMBER:
b += '[';
t = 2;
break;
case LUA_TSTRING:
b += "{\"";
b += lua_tostring(s, -2);
b += "\":";
t = 1;
break;
default:
lua_pop(s, 1);
return -1;
} switch (lua_type(s, -1)) {
case LUA_TBOOLEAN:
b += (lua_toboolean(s, -1) == 1) ? "true" : "false";
break;
case LUA_TNUMBER: {
double dv = lua_tonumber(s, -1);
if (lua_isintnum(dv))
sprintf_s(sznum, 128, "%I64d", (long long)dv);
else
sprintf_s(sznum, 128, "%lf", dv);
b += sznum;
break;
}
case LUA_TSTRING:
b += '"';
b += lua_tostring(s, -1);
b += '"';
break;
case LUA_TTABLE:
if (table_to_json(-2)) {
lua_pop(s, 1);
return -1;
}
break;
default:
lua_pop(s, 1);
return -1;
} lua_pop(s, 1);
while (lua_next(s, n)) { switch (lua_type(s, -2)) {
case LUA_TNUMBER:
b += ',';
break;
case LUA_TSTRING:
b += ",\"";
b += lua_tostring(s, -2);
b += "\":";
break;
default:
lua_pop(s, 1);
return -1;
} switch (lua_type(s, -1)) {
case LUA_TBOOLEAN:
b += (lua_toboolean(s, -1) == 1) ? "true" : "false";
break;
case LUA_TNUMBER: {
double dv = lua_tonumber(s, -1);
if (lua_isintnum(dv))
sprintf_s(sznum, 128, "%I64d", (long long)dv);
else
sprintf_s(sznum, 128, "%lf", dv);
b += sznum;
break;
}
case LUA_TSTRING:
b += '"';
b += lua_tostring(s, -1);
b += '"';
break;
case LUA_TTABLE:
if (table_to_json(-2)) {
lua_pop(s, 1);
return -1;
}
break;
default:
lua_pop(s, 1);
return -1;
} lua_pop(s, 1); } b += t == 1 ? '}' : ']';
return 0;
} int ljson_convert::json_to_table(const char *_Text, int _Len) {
if (!ec_mode)
{
if (!pgbk->load_string(_Text, _Len, true)) {
return -1;
}
}
else
{
if (!putf8->load_string(_Text, _Len, true))
return -1;
} auto root = jt.get_root();
if (!root)
return -1;
json_to_object(root->begin());
return 0;
} void ljson_convert::json_to_object(aqx::jsize_t _Ref) {
for (auto v = jt.get_val(_Ref); v != nullptr; v = v->next(jt)) {
switch (v->type()) {
case aqx::jsvt_null:
lua_pushstring(s, v->skey(jt));
lua_pushnil(s);
lua_settable(s, -3);
break;
case aqx::jsvt_string:
lua_pushstring(s, v->skey(jt));
lua_pushstring(s, v->tostring(jt));
lua_settable(s, -3);
break;
case aqx::jsvt_number:
{
lua_pushstring(s, v->skey(jt));
double dv = v->tonumber();
if (lua_isintnum(dv))
lua_pushinteger(s, (intptr_t)dv);
else
lua_pushnumber(s, dv);
lua_settable(s, -3);
break;
}
case aqx::jsvt_boolean:
lua_pushstring(s, v->skey(jt));
lua_pushboolean(s, v->toboolean());
lua_settable(s, -3);
break;
case aqx::jsvt_object: {
auto n = v->toobject(jt);
if (!n->size())
break;
lua_pushstring(s, v->skey(jt));
lua_newtable(s);
json_to_object(n->begin());
lua_settable(s, -3);
break;
}
case aqx::jsvt_group: {
auto n = v->toobject(jt);
if (!n->size()) {
break;
}
lua_pushstring(s, v->skey(jt));
lua_newtable(s);
json_to_group(n->begin());
lua_settable(s, -3);
break;
}
} }
} void ljson_convert::json_to_group(aqx::jsize_t _Ref) {
int i = 1; for (auto v = jt.get_val(_Ref); v != nullptr; v = v->next(jt)) {
switch (v->type()) {
case aqx::jsvt_null:
lua_pushnil(s);
lua_rawseti(s, -2, i++);
break;
case aqx::jsvt_string:
lua_pushstring(s, v->tostring(jt));
lua_rawseti(s, -2, i++);
break;
case aqx::jsvt_number: {
double dv = v->tonumber();
if (lua_isintnum(dv))
lua_pushinteger(s, (intptr_t)dv);
else
lua_pushnumber(s, dv);
lua_rawseti(s, -2, i++);
break;
}
case aqx::jsvt_boolean:
lua_pushboolean(s, v->toboolean());
break;
case aqx::jsvt_object: {
auto n = v->toobject(jt);
if (!n->size())
break;
lua_newtable(s);
json_to_object(n->begin());
lua_rawseti(s, -2, i++);
break;
}
case aqx::jsvt_group: {
auto n = v->toobject(jt);
if (!n->size())
break;
lua_newtable(s);
json_to_group(n->begin());
lua_rawseti(s, -2, i++);
break;
}
} }
} ljson_convert *get_ljson_convert(lua_State *s) {
lua_getglobal(s, "__ljsonlib_convert_");
if (lua_isnil(s, -1))
return nullptr;
return (ljson_convert*)lua_touserdata(s, -1);
} int lua_table_to_json(lua_State *s)
{
ljson_convert *pjc = get_ljson_convert(s);
if (!pjc)
return 0;
if (!lua_gettop(s))
return 0;
if (lua_type(s, 1) != LUA_TTABLE)
return 0;
pjc->b.clear();
if (pjc->table_to_json(1)) {
pjc->b.clear();
}
lua_pushstring(s, pjc->b.c_str());
return 1;
} int lua_table_from_json(lua_State *s) {
ljson_convert *pjc = get_ljson_convert(s);
if (!pjc)
return 0;
if (!lua_gettop(s))
return 0;
if (lua_type(s, 1) != LUA_TSTRING)
return 0;
lua_newtable(s); if (!pjc->json_to_table(lua_tostring(s, 1), -1)) {
return 1;
} lua_pop(s, 1);
return 0;
} ljson_convert *lua_openljsonlib(lua_State *s, const char *_CharEncoding)
{
ljson_convert *pjc = get_ljson_convert(s);
if (pjc)return pjc;
pjc = new ljson_convert(s, (strstr(_CharEncoding, "utf") == nullptr) ? 0 : 1);
lua_pushlightuserdata(s, pjc);
lua_setglobal(s, "__ljsonlib_convert_"); lua_getglobal(s, "table");
lua_pushcfunction(s, lua_table_to_json);
lua_setfield(s, -2, "tojson"); lua_pushcfunction(s, lua_table_from_json);
lua_setfield(s, -2, "fromjson"); return pjc;
}
// ConsoleApplication2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// #include "pch.h"
#include <thread>
#include <iostream>
#pragma comment(lib, "lua54.lib")
#include "lxsharelib.h"
#include "ljsonlib.h"
int main(int argc, char **argv)
{
lua_State *s = luaL_newstate();
luaL_openlibs(s); //使用这个接口,向lua本身的table对象中,添加两个函数table.tojson和table.fromjson
auto p = lua_openljsonlib(s, "");//第2个参数可以传入"utf8"来应对utf8的lua文件,默认的情况下是gbk
if (luaL_dofile(s, "G:\\vs2017\\ConsoleApplication2\\x64\\Release\\script\\testjson.lua"))
printf("%s\n", lua_tostring(s, -1));
lua_close(s); //用完之后,需要自己释放掉内存,这个问题没什么好办法解决,除非扩展到lua源码中,或者给lua_close实现回调
delete p; return 0;
}

测试脚本代码:

-- testjson.lua

local t = {
x = 3.14159,
y = 2,
z = {10,20,30,40,50}
}; local json_text = table.tojson(t);
print(json_text);--{"z":[10,20,30,40,50],"y":2,"x":3.141590} local t2 = table.fromjson('{"a":1.21e-3,"b":2,"c":[3,4,5,6,7,"abcde"],"d":[]}'); print(t2)
--[[
b:2
a:0.00121
c:table: 000001C74BABABE0
]]
for i, e in pairs(t2) do
print(i..':'..tostring(e));
end --[[
1:3
2:4
3:5
4:6
5:7
6:abcde
]]
for i, e in ipairs(t2.c) do
print(i..':'..e);
end

{"y":2,"x":3.141590,"z":[10,20,30,40,50]}
table: 0000025A15D5EFC0
a:0.00121
c:table: 0000025A15D7A340
b:2
1:3
2:4
3:5
4:6
5:7
6:abcde

lua table与json的之间的互相转换高性能c++实现的更多相关文章

  1. cocos2d-x lua table与json的转换

    cocos2d-x lua table与json的转换 version: cocos2d-x 3.6 1.引入json库 require("src/cocos/cocos2d/json&qu ...

  2. 前端页面使用 Json对象与Json字符串之间的互相转换

    前言 在前端页面很多时候都会用到Json这种格式的数据,最近没有前端,后端的我也要什么都要搞,对于Json对象与Json字符串之间的转换终于摸清楚了几种方式,归纳如下! 一:Json对象转换为json ...

  3. 我为什么要再给lua写一个json模块

    最近要给自己编写的服务器加上json解析模块.根据我当前的项目,可以预测服务器中使用json的地方: 通信.由于与客户端通信使用google protocolbuffer,仅在与SDK通信中使用jso ...

  4. 高并发 Nginx+Lua OpenResty系列(7)——Lua开发库json

    JSON库 在进行数据传输时JSON格式目前应用广泛,因此从Lua对象与JSON字符串之间相互转换是一个非常常见的功能:目前Lua也有几个JSON库,如:cjson.dkjson.其中cjson的语法 ...

  5. Json——使用Json jar包实现Json字符串与Java对象或集合之间的互相转换

    总结一下利用Json相关jar包实现Java对象和集合与Json字符串之间的互相转换: 1.创建的User类: package com.ghj.packageofdomain; public clas ...

  6. cocos2d-x lua table数据存储

    cocos2d-x lua table数据存储 version: cocos2d-x 3.6 1. 将table转为json http://blog.csdn.net/songcf_faith/art ...

  7. Lua 数据类型和 Redis 数据类型之间转换

    当 Lua 通过 call() 或 pcall() 函数执行 Redis 命令的时候,命令的返回值会被转换成 Lua 数据结构. 同样地,当 Lua 脚本在 Redis 内置的解释器里运行时,Lua ...

  8. lua table integer index 特性

    table.maxn (table) Returns the largest positive numerical index of the given table, or zero if the t ...

  9. 树形打印lua table表

    为方便调试lua程序,往往想以树的形式打印出一个table,以观其表内数据.以下罗列了三种种关于树形打印lua table的方法;法一 local print = print local tconca ...

随机推荐

  1. LVDS DP等显示器接口简介

    LVDS 产品传输速率从几百Mbps到2Gbps.它是电流驱动的,他通过在接收端放置一个负载而得到的电压,当电流正向流动,接收端输出为1,反之为0,它的摆幅250mV-450mV. lvds 即低压差 ...

  2. Ubuntu virtualenv 创建 python3 虚拟环境 激活 退出

    首先默认安装了virtualenv 创建python3虚拟环境 your-name@node-name:~/virtual_env$ virtualenv -p /usr/bin/python3 py ...

  3. 学好Python不加班系列之SCRAPY爬虫框架的使用

    scrapy是一个爬虫中封装好的一个明星框架.具有高性能的持久化存储,异步的数据下载,高性能的数据解析,分布式. 对于初学者来说还是需要有一定的基础作为铺垫的学习.我将从下方的思维导图中进行逐步的解析 ...

  4. docker安装pxc集群

      前言 现在mysql自建集群方案有多种,keepalived.MHA.PXC.MYSQL主备等,但是目前根据自身情况和条件,选择使用pxc的放来进行搭建,最大的好处就是,多主多备,即主从一体,没有 ...

  5. JDK 之 HttpClient(jdk11)

    HttpClient 简介 java.net.http.HttpClient 是 jdk11 中正式启用的一个 http 工具类(其实早在 jdk9 的时候就已经存在了,只是处于孵化期),官方寓意为想 ...

  6. VMware Workstation 无法连接到虚拟机。请确保您有权运行该程序、访问该程序使用的所有目录以及访问所有临时文件目录。 VMware Authorization Service 当前未运行

    VMware Workstation 无法连接到虚拟机.请确保您有权运行该程序.访问该程序使用的所有目录以及访问所有临时文件目录. VMware Authorization Service 当前未运行 ...

  7. script标签引入vue方式开发如何写组件

    title: script标签引入vue方式开发如何写组件 date: 2020-05-08 sidebarDepth: 2 tags: vue 组件 script 标签 categories: vu ...

  8. 96-00年CPU功耗感知调度研究

    最近读了一些1996-2000年的通过调度来降低cpu能耗的文章,主要文章有[1] [2] [3] [4] [5], 简单总结一些该时期单核CPU功耗感知的调度策略. 该时期还出现了很多关于低功耗电路 ...

  9. <C#任务导引教程>练习八

    //66,静态成员与非静态成员的访问方式using System;class Text{    public int x;    public static int y;//静态数据成员    voi ...

  10. [loj3284]Exercise

    对于一个排列$p_{i}$,假设循环长度依次为$x_{1},x_{2},...,x_{m}$,那么所需步数即${\rm lcm}_{i=1}^{m}x_{i}$ 由于是乘积,因此可以枚举素数$p$,并 ...