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

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. 基于屏幕空间的实时全局光照(Real-time Global Illumination Based On Screen Space)

    目录 Reflective Shadow Maps(RSM) RSM 的重要性采样 RSM 的应用与缺陷 Screen Space Ambient Occulsion(SSAO) SSAO Blur ...

  2. NavigationView使用简介

    Android支持直接创建带有NavigationView的Activity,这里主要介绍NavigationView的逻辑. NavigationView通常是跟DrawerLayout一起使用.D ...

  3. hdu 3047 Zjnu Stadium(并查集)

    题意: 300个座位构成一个圈. 有N个人要入座. 共有M个说明 :A B X ,代表B坐在A顺时针方向第X个座位上.如果这个说明和之前的起冲突,则它是无效的. 问总共有多少个无效的. 思路: 并查集 ...

  4. cf13C Sequence(DP)

    题意: N个数.a1...aN. 对于每个数而言,每一步只能加一或减一. 问最少总共需要多少步使得新序列是非递减序列. N (1 ≤ N ≤ 5000) 思路: *一个还不知道怎么证明的结论(待证): ...

  5. popStar手机游戏机机对战程序

    DFS算,五分钟如果答案没有更新,那个解一般来说就很优了. #include <cstdio> #include <iostream> #include <string. ...

  6. Obsidian中使用Calendar插件快捷建立日记、周记

    Calendar插件 Calendar插件是我第一个安装使用的插件,插件可以帮助我们很便捷的记录每天的工作 插件效果图 插件下载 下载地址 插件安装 # Obsidian如何手动下载并安装插件-以看板 ...

  7. eclipse配置Tomcat和Tomcat出现无效端口解决办法

    一.eclipse配置Tomcat 1. 按图选择window-preferences 2在server处选择runtime environment . 3.点击右侧add,选择自己的Tomcat版本 ...

  8. Tcpdump 常用命令、参数记录

    一.介绍 一个关于Centos  Tcpdump 的个人工作总结. 二.参数介绍: 1. -i:   指定要进行抓包的网卡 2.-s0 :表示每个报文的大小是接收到的指定大小,如果没有这个选项,则超过 ...

  9. VNC服务器的搭建(带图形化支持)

    环境:centos7.6最小化安装 图形化支持 如果希望安装简单的图形支持的话,仅包含gnome的最最最最基础的包的话可以使用以下命令 yum groups install "X Windo ...

  10. Screenshot 库和Collections 库

    一.screenShot 是 robot framework的标准类库,用于截取当前窗口,需要手动加载. 示例: 运行结果: 二.Collections 库 Collections 库同样为 Robo ...