c++ json
复制自github:https://github.com/sukai33/yazi-json
Json.h
#ifndef YAZIJSON_H
#define YAZIJSON_H
#include <string>
using std::string;
#include <list>
#include <map>
namespace yazi {
namespace json {
class Json
{
public:
enum Type
{
json_null = 0, // null value
json_bool, // bool value
json_int, // integer value
json_double, // double value
json_string, // string value
json_array, // array value
json_object // object value
};
Json();
Json(Type type);
Json(bool value);
Json(int value);
Json(double value);
Json(const char * value);
Json(const string & value);
Json(const Json & other);
~Json();
Type type() const;
bool isNull() const;
bool isBool() const;
bool isInt() const;
bool isDouble() const;
bool isString() const;
bool isArray() const;
bool isObject() const;
bool asBool() const;
int asInt() const;
double asDouble() const;
string asString() const;
// number of values in array or object
int size() const;
// return true if empty array, empty object, or null, otherwise, false.
bool empty() const;
void clear();
bool has(int index);
bool has(const char * key);
bool has(const string & key);
void remove(int index);
void remove(const char * key);
void remove(const string & key);
// append value to array at the end.
void append(const Json & value);
Json & operator = (const Json & other);
bool operator == (const Json & other);
bool operator != (const Json & other);
Json & operator [] (int index);
Json & operator [] (const char * key);
Json & operator [] (const string & key);
operator bool();
operator int();
operator double();
operator string();
void parse(const string & str);
string str() const;
typedef std::list<Json>::iterator iterator;
iterator begin()
{
return (m_value.m_array)->begin();
}
iterator end()
{
return (m_value.m_array)->end();
}
private:
void copy(const Json & other);
private:
union Value
{
bool m_bool;
int m_int;
double m_double;
std::string * m_string;
std::list<Json> * m_array;
std::map<string, Json> * m_object;
};
Type m_type;
Value m_value;
};
}}
#endif // !YAZIJSON_H
Json.cpp
#include <sstream>
using std::stringstream;
#include <stdexcept>
#include "Json.h"
#include "Parser.h"
using namespace yazi::json;
Json::Json() : m_type(json_null)
{
}
Json::Json(Type type) : m_type(type)
{
switch (m_type)
{
case json_null:
break;
case json_bool:
m_value.m_bool = false;
break;
case json_int:
m_value.m_int = 0;
break;
case json_double:
m_value.m_double = 0.0;
break;
case json_string:
m_value.m_string = new string("");
break;
case json_array:
m_value.m_array = new std::list<Json>();
break;
case json_object:
m_value.m_object = new std::map<string, Json>();
default:
break;
}
}
Json::Json(bool value) : m_type(json_bool)
{
m_value.m_bool = value;
}
Json::Json(int value) : m_type(json_int)
{
m_value.m_int = value;
}
Json::Json(double value) : m_type(json_double)
{
m_value.m_double = value;
}
Json::Json(const char * value) : m_type(json_string)
{
m_value.m_string = new string(value);
}
Json::Json(const string & value) : m_type(json_string)
{
m_value.m_string = new string(value);
}
Json::Json(const Json & other) : m_type(json_null)
{
copy(other);
}
Json::~Json()
{
}
Json::Type Json::type() const
{
return m_type;
}
bool Json::isNull() const
{
return m_type == json_null;
}
bool Json::isBool() const
{
return m_type == json_bool;
}
bool Json::isInt() const
{
return m_type == json_int;
}
bool Json::isDouble() const
{
return m_type == json_double;
}
bool Json::isString() const
{
return m_type == json_string;
}
bool Json::isArray() const
{
return m_type == json_array;
}
bool Json::isObject() const
{
return m_type == json_object;
}
bool Json::asBool() const
{
if (m_type == json_bool)
{
return m_value.m_bool;
}
throw std::logic_error("function Json::asBool value type error");
}
int Json::asInt() const
{
if (m_type == json_int)
{
return m_value.m_int;
}
throw std::logic_error("function Json::asInt value type error");
}
double Json::asDouble() const
{
if (m_type == json_double)
{
return m_value.m_double;
}
throw std::logic_error("function Json::asDouble value type error");
}
string Json::asString() const
{
if (m_type == json_string)
{
return *(m_value.m_string);
}
throw std::logic_error("function Json::asString value type error");
}
void Json::copy(const Json & other)
{
m_type = other.m_type;
//m_value.m_double = 0;
m_value = other.m_value;
}
int Json::size() const
{
switch (m_type)
{
case json_array:
return (m_value.m_array)->size();
case json_object:
return (m_value.m_object)->size();
default:
break;
}
throw std::logic_error("function Json::size value type error");
}
bool Json::empty() const
{
switch (m_type)
{
case json_null:
return true;
case json_array:
return (m_value.m_array)->empty();
case json_object:
return (m_value.m_object)->empty();
default:
break;
}
return false;
}
void Json::clear()
{
switch (m_type)
{
case json_null:
case json_bool:
case json_int:
case json_double:
break;
case json_string:
{
delete m_value.m_string;
}
break;
case json_array:
{
for (auto it = (m_value.m_array)->begin(); it != (m_value.m_array)->end(); it++)
{
it->clear();
}
delete m_value.m_array;
}
break;
case json_object:
{
for (auto it = (m_value.m_object)->begin(); it != (m_value.m_object)->end(); it++)
{
it->second.clear();
}
delete m_value.m_object;
}
break;
default:
break;
}
m_type = json_null;
}
bool Json::has(int index)
{
if (m_type != json_array)
{
return false;
}
int size = (m_value.m_array)->size();
return (index >= 0) && (index < size);
}
bool Json::has(const char * key)
{
string name(key);
return has(name);
}
bool Json::has(const string & key)
{
if (m_type != json_object)
{
return false;
}
return (m_value.m_object)->find(key) != (m_value.m_object)->end();
}
void Json::remove(int index)
{
if (m_type != json_array)
{
return;
}
int size = (m_value.m_array)->size();
if (index < 0 || index >= size)
{
return;
}
auto it = (m_value.m_array)->begin();
for (int i = 0; i < index; i++)
{
it++;
}
it->clear();
(m_value.m_array)->erase(it);
}
void Json::remove(const char * key)
{
string name = key;
remove(name);
}
void Json::remove(const string & key)
{
if (m_type != json_object)
{
return;
}
auto it = (m_value.m_object)->find(key);
if (it != (m_value.m_object)->end())
{
it->second.clear();
(m_value.m_object)->erase(key);
}
}
void Json::append(const Json & value)
{
if (m_type != json_array)
{
clear();
m_type = json_array;
m_value.m_array = new std::list<Json>();
}
(m_value.m_array)->push_back(value);
}
Json & Json::operator = (const Json & other)
{
clear();
copy(other);
return *this;
}
bool Json::operator == (const Json & other)
{
if (m_type != other.type())
{
return false;
}
switch (m_type)
{
case json_null:
return true;
case json_bool:
return (m_value.m_bool == other.m_value.m_bool);
case json_int:
return (m_value.m_int == other.m_value.m_int);
case json_double:
return (m_value.m_double == other.m_value.m_double);
case json_string:
return *(m_value.m_string) == *(other.m_value.m_string);
case json_array:
return m_value.m_array == other.m_value.m_array;
case json_object:
return m_value.m_object == other.m_value.m_object;
default:
break;
}
return false;
}
bool Json::operator != (const Json & other)
{
return !(*this == other);
}
Json & Json::operator [] (int index)
{
if (index < 0)
{
throw std::logic_error("function Json::operator [int] index less than 0");
}
if (m_type != json_array)
{
clear();
m_type = json_array;
m_value.m_array = new std::list<Json>();
}
int size = (m_value.m_array)->size();
if (index >= 0 && index < size)
{
auto it = (m_value.m_array)->begin();
for (int i = 0; i < index; i++)
{
it++;
}
return *it;
}
if (index >= size)
{
for (int i = size; i <= index; i++)
{
(m_value.m_array)->push_back(Json());
}
}
return (m_value.m_array)->back();
}
Json & Json::operator [] (const char * key)
{
string name = key;
return (*this)[name];
}
Json & Json::operator [] (const string & key)
{
if (m_type != json_object)
{
clear();
m_type = json_object;
m_value.m_object = new std::map<string, Json>();
}
return (*(m_value.m_object))[key];
}
Json::operator bool()
{
if (m_type != json_bool)
{
throw std::logic_error("function Json::operator (bool) requires bool value");
}
return m_value.m_bool;
}
Json::operator int()
{
if (m_type != json_int)
{
throw std::logic_error("function Json::operator (int) requires int value");
}
return m_value.m_int;
}
Json::operator double()
{
if (m_type != json_double)
{
throw std::logic_error("function Json::operator (double) requires double value");
}
return m_value.m_double;
}
Json::operator string()
{
if (m_type != json_string)
{
throw std::logic_error("function Json::operator (string) requires string value");
}
return *(m_value.m_string);
}
void Json::parse(const string & str)
{
Parser parser;
parser.load(str);
*this = parser.parse();
}
string Json::str() const
{
stringstream ss;
switch (m_type)
{
case json_null:
ss << "null";
break;
case json_bool:
if (m_value.m_bool)
{
ss << "true";
}
else
{
ss << "false";
}
break;
case json_int:
ss << m_value.m_int;
break;
case json_double:
ss << m_value.m_double;
break;
case json_string:
ss << "\"" << *(m_value.m_string) << "\"";
break;
case json_array:
{
ss << "[";
for (auto it = (m_value.m_array)->begin(); it != (m_value.m_array)->end(); it++)
{
if (it != (m_value.m_array)->begin())
{
ss << ",";
}
ss << (*it).str();
}
ss << "]";
}
break;
case json_object:
{
ss << "{";
for (auto it = (m_value.m_object)->begin(); it != (m_value.m_object)->end(); it++)
{
if (it != (m_value.m_object)->begin())
{
ss << ",";
}
ss << "\"" << it->first << "\":" << it->second.str();
}
ss << "}";
}
break;
default:
break;
}
return ss.str();
}
Parser.h
#ifndef YAZIPARSER_H
#define YAZIPARSER_H
#include <string>
using namespace std;
#include "Json.h"
namespace yazi {
namespace json {
class Parser
{
public:
Parser();
~Parser();
void load(const string & str);
Json parse();
private:
void skip_white_space();
char get_next_token();
Json parse_null();
Json parse_bool();
Json parse_number();
string parse_string();
Json parse_array();
Json parse_object();
bool in_range(int x, int lower, int upper)
{
return (x >= lower && x <= upper);
}
private:
string m_str;
size_t m_idx;
};
}}
#endif // !YAZIPARSER_H
Parser.cpp
#include <string.h>
#include <stdexcept>
#include <cstdlib>
using namespace std;
#include "Parser.h"
using namespace yazi::json;
Parser::Parser() : m_idx(0)
{
}
Parser::~Parser()
{
}
void Parser::load(const string & str)
{
m_str = str;
m_idx = 0;
}
void Parser::skip_white_space()
{
while (m_str[m_idx] == ' ' || m_str[m_idx] == '\r' || m_str[m_idx] == '\n' || m_str[m_idx] == '\t')
m_idx++;
}
char Parser::get_next_token()
{
skip_white_space();
if (m_idx == m_str.size())
throw std::logic_error("unexpected end of input");
return m_str[m_idx++];
}
Json Parser::parse()
{
char ch = get_next_token();
switch (ch)
{
case 'n':
m_idx--;
return parse_null();
case 't':
case 'f':
m_idx--;
return parse_bool();
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
m_idx--;
return parse_number();
case '"':
return Json(parse_string());
case '[':
return parse_array();
case '{':
return parse_object();
default:
break;
}
throw std::logic_error("unexpected character in parse json");
}
Json Parser::parse_null()
{
if (m_str.compare(m_idx, 4, "null") == 0)
{
m_idx += 4;
return Json();
}
throw std::logic_error("parse null error");
}
Json Parser::parse_bool()
{
if (m_str.compare(m_idx, 4, "true") == 0)
{
m_idx += 4;
return Json(true);
}
if (m_str.compare(m_idx, 5, "false") == 0)
{
m_idx += 5;
return Json(false);
}
throw std::logic_error("parse bool error");
}
Json Parser::parse_number()
{
size_t pos = m_idx;
if (m_str[m_idx] == '-')
m_idx++;
// integer part
if (m_str[m_idx] == '0')
{
m_idx++;
}
else if (in_range(m_str[m_idx], '1', '9'))
{
m_idx++;
while (in_range(m_str[m_idx], '0', '9'))
{
m_idx++;
}
}
else
{
throw std::logic_error("invalid character in number");
}
if (m_str[m_idx] != '.')
{
return Json(std::atoi(m_str.c_str() + pos));
}
// decimal part
m_idx++;
if (!in_range(m_str[m_idx], '0', '9'))
{
throw std::logic_error("at least one digit required in fractional part");
}
while (in_range(m_str[m_idx], '0', '9'))
{
m_idx++;
}
return Json(std::atof(m_str.c_str() + pos));
}
string Parser::parse_string()
{
int pos = m_idx;
while (true)
{
if (m_idx == m_str.size())
{
throw std::logic_error("unexpected end of input in string");
}
char ch = m_str[m_idx++];
if (ch == '"')
{
break;
}
// The usual case: non-escaped characters
if (ch == '\\')
{
ch = m_str[m_idx++];
switch (ch)
{
case 'b':
case 't':
case 'n':
case 'f':
case 'r':
case '"':
case '\\':
break;
case 'u':
m_idx += 4;
break;
default:
break;
}
}
}
return m_str.substr(pos, m_idx - pos - 1);
}
Json Parser::parse_array()
{
Json arr(Json::json_array);
char ch = get_next_token();
if (ch == ']')
{
return arr;
}
m_idx--;
while (true)
{
arr.append(parse());
ch = get_next_token();
if (ch == ']')
{
break;
}
if (ch != ',')
{
throw std::logic_error("expected ',' in array");
}
}
return arr;
}
Json Parser::parse_object()
{
Json obj(Json::json_object);
char ch = get_next_token();
if (ch == '}')
{
return obj;
}
m_idx--;
while (true)
{
ch = get_next_token();
if (ch != '"')
{
throw std::logic_error("expected '\"' in object");
}
string key = parse_string();
ch = get_next_token();
if (ch != ':')
{
throw std::logic_error("expected ':' in object");
}
obj[key] = parse();
ch = get_next_token();
if (ch == '}')
{
break;
}
if (ch != ',')
{
throw std::logic_error("expected ',' in object");
}
}
return obj;
}