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

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. Go语言核心36讲(Go语言进阶技术八)--学习笔记

    14 | 接口类型的合理运用 前导内容:正确使用接口的基础知识 在 Go 语言的语境中,当我们在谈论"接口"的时候,一定指的是接口类型.因为接口类型与其他数据类型不同,它是没法被实 ...

  2. 8M的摄像头,30fps摄像时,60hz的LCD刷新频率,请问camera每秒向BB传输多少数据,如何计算

    8M的摄像头,30fps摄像时,60hz的LCD刷新频率,请问camera每秒向BB传输多少数据,如何计算 xiang2012 Post at 2012/8/7 10:37:33 8M的摄像头,30f ...

  3. crond 任务调度

    crontab 进行定时任务的设置 任务调度:是指系统在某个时间执行的特定的命令或程序. 任务调度分类: 系统工作:有些重要的工作必须周而复始地执行.如病毒扫描等 个别用户工作:个别用户可能希望执行某 ...

  4. node 中第三方模块的加载过程原理

    node 中第三方模块的加载过程原理 凡是第三方模块都必须通过 npm 来下载 使用的时候就可以通过require('包名') 的方式来进行加载才可以使用 不可能有任何一个第三方包和核心模块的名字是一 ...

  5. 大一C语言学习笔记(3)---对于程序员来说,学历和能力,到底哪个重要?

    在高考失利后,我合理地萎靡一段时间,振作起来之后选择了我憧憬了10年的计算机专业---软件工程.但由于分数受限,也是选择了二本普通院校黑科技(我当然爱她,我的母校),而因为学历上的自卑,让我有了想考研 ...

  6. SpringBoot Actuator — 埋点和监控

    项目中看到了有埋点监控.报表.日志分析,有点兴趣想慢慢捣鼓一下 1. 数据埋点 监控机器环境的性能和业务流程或逻辑等各项数据,并根据这些数据生成对应的指标,那么我们就称为数据埋点.比如我们想知道某个接 ...

  7. Alpha冲刺.2李霆政

    一.基本情况 队名:不行就摆了吧 组长博客:https://www.cnblogs.com/Microsoft-hc/p/15534079.html 小组人数: 8 二.冲刺概况汇报 谢小龙 过去两天 ...

  8. 用js实现web端录屏

    用js实现web端录屏 原创2021-11-14 09:30·无意义的路过 随着互联网技术飞速发展,网页录屏技术已趋于成熟.例如可将录屏技术运用到在线考试中,实现远程监考.屏幕共享以及录屏等:而在我们 ...

  9. excel (2)

    ... poi 3.8 import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; ...

  10. 菜鸡的Java笔记 国际化程序实现原理

    国际化程序实现原理 Lnternationalization        1. Locale 类的使用        2.国家化程序的实现,资源读取                所谓的国际化的程序 ...