json工具

该工具测试比jsoncpp,protobuf效率跟高。该工具主要有两个模块json主体结构和parser解析结构。知识点C++98/C++11/C++14,makefile等不需要使用第三方库支持跨平台。

1.json主体结构(json.h json.cc)

主要对常见的类型进行封装成json类

json.h

#pragma once
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <fstream>
#include <unordered_map>
using namespace std;

namespace yazi
{
    namespace json
    {
        class Json
        {
        public:
            typedef std::vector<Json>::iterator iterator;
            iterator begin()
            {
                return _vaule._array->begin();
            }
            iterator end()
            {
                return _vaule._array->end();
            }
            enum Type
            {
                json_null = 0,
                json_bool,
                json_int,
                json_double,
                json_string,
                json_array,
                json_object
            };
            Json();
            Json(bool vaule);
            Json(int vaule);
            Json(double vaule);
            Json(const char* vaule);
            Json(const std::string& vaule);
            Json(Type type);
            Json(const Json& other);

            operator bool();
            operator int();
            operator double();
            operator string();
            Json& operator[](int index);
            Json& operator[](const char* key);
            Json& operator[](const std::string& key);
            void operator=(const Json& other);
            bool operator==(const Json& other);
            bool operator!=(const Json& other);
            //Json& operator*();
            void append(const Json& other);
            size_t size() const;
            string str()const;
            void copy(const Json& other);
            void clear();
            bool isNull()const { return _type == json_null; }
            bool isBool()const { return _type == json_bool; }
            bool isInt()const { return _type == json_int; }
            bool isDouble()const { return _type == json_double; }
            bool isString()const { return _type == json_string; }
            bool isArray()const { return _type == json_array; }
            bool isObject()const { return _type == json_object; }

            bool asBool() const;
            int asInt()const;
            double asDouble()const;
            std::string asString()const;


            bool has(int index);
            bool has(const char* key);
            bool has(const std::string& key);


            void remove(int index);
            void remove(const char* key);
            void remove(const std::string& key);


            void parse(const std::string& str);
        private: 
            union Vaule
            {
                bool _bool;
                int _int;
                double _double;
                std::string* _string;
                std::vector<Json>* _array;
                std::map<std::string, Json>* _object;
            };
            Type _type;
            Vaule _vaule;
        };
    }
}

Json.cc

#include "json.h"
#include "parser.h"
using namespace yazi::json;

Json::Json() : _type(json_null)
{
}
Json::Json(bool vaule) : _type(json_bool)
{
    _vaule._bool = vaule;
}
Json::Json(int vaule) : _type(json_int)
{
    _vaule._int = vaule;
}
Json::Json(double vaule) : _type(json_double)
{
    _vaule._double = vaule;
}
Json::Json(const char* vaule) : _type(json_string)
{
    _vaule._string = new std::string(vaule);
}
Json::Json(const std::string& vaule) : _type(json_string)
{
    _vaule._string = new std::string(vaule);
}
Json::Json(Type type) : _type(type)
{
    switch (_type)
    {
    case json_null:
        break;
    case json_bool:
        _vaule._bool = false;
        break;
    case json_int:
        _vaule._int = 0;
        break;
    case json_double:
        _vaule._double = 0.0;
        break;
    case json_string:
        _vaule._string = new std::string("");
        break;
    case json_array:
        _vaule._array = new std::vector<Json>();
        break;
    case json_object:
        _vaule._object = new std::map<std::string, Json>();
        break;
    default:
        break;
    }
}
Json::Json(const Json& other)
{
    copy(other);
}

Json::operator bool()
{
    if (_type != json_bool)
    {
        throw new logic_error("type error,not bool vaule");
    }
    return _vaule._bool;
}
Json::operator int()
{
    if (_type != json_int)
    {
        throw new logic_error("type error,not int vaule");
    }
    return _vaule._int;
}
Json::operator double()
{
    if (_type != json_double)
    {
        throw new logic_error("type error,not double vaule");
    }
    return _vaule._double;
}
Json::operator string()
{
    if (_type != json_string)
    {
        throw new logic_error("type error,not  string vaule");
    }
    return *(_vaule._string);
}

Json& Json::operator[](int index)
{
    if (_type != json_array)
    {
        clear();
        _type = json_array;
        _vaule._array = new std::vector<Json>();
    }
    // if(index < 0)
    // {
    //     throw new logic_error("array[] index < 0");
    // }
    size_t size = (_vaule._array)->size();
    if (index >= size) // 扩容
    {
        for (size_t i = size; i <= index; ++i)
        {
            (_vaule._array)->push_back(Json());
        }
    }
    return (_vaule._array)->at(index);
}
Json& Json::operator[](const char* key)
{
    std::string name(key);
    return (*(this))[name];
}
Json& Json::operator[](const std::string& key)
{
    if (_type != json_object)
    {
        clear();
        _type = json_object;
        _vaule._object = new std::map<std::string, Json>();
    }
    return (*(_vaule._object))[key];
}
void Json::operator=(const Json& other)
{
    clear();
    copy(other);
}
void Json::append(const Json& other)
{
    if (_type != json_array)
    {
        _type = json_array;
        _vaule._array = new std::vector<Json>();
    }
    (_vaule._array)->push_back(other);
}
size_t Json::size() const
{
    if (_type != json_array)
    {
        throw new logic_error("type error,not array vaule");
    }
    return (_vaule._array)->size();
}
string Json::str() const
{
    std::stringstream ss;
    switch (_type)
    {
    case json_null:
        ss << "null";
        break;
    case json_bool:
        if (_vaule._bool)
        {
            ss << "true";
        }
        else
        {
            ss << "false";
        }
        break;
    case json_int:
        ss << _vaule._int;
        break;
    case json_double:
        ss << _vaule._double;
        break;
    case json_string:
        ss << '\"' << *(_vaule._string) << '\"';
        break;
    case json_array:
    {
        ss << '[';
        for (auto it = (_vaule._array)->begin(); it != (_vaule._array)->end(); ++it)
        {
            if (it != (_vaule._array)->begin())
            {
                ss << ',';
            }
            ss << it->str();
        }
        ss << ']';
        break;
    }
    case json_object:
    {
        ss << '{';
        for (auto it = (_vaule._object)->begin(); it != (_vaule._object)->end(); ++it)
        {
            if (it != (_vaule._object)->begin())
            {
                ss << ',';
            }
            ss << '\"' << it->first << '\"' << ':' << it->second.str();
        }
        ss << '}';
        break;
    }
    default:
        break;
    }
    return ss.str();
}
void Json::copy(const Json& other)
{
    _type = other._type;
    switch (_type)
    {
    case json_null:
        break;
    case json_bool:
        _vaule._bool = other._vaule._bool;
        break;
    case json_int:
        _vaule._int = other._vaule._int;
        break;
    case json_double:
        _vaule._double = other._vaule._double;
        break;
    case json_string:
        _vaule._string = other._vaule._string;
        break;
    case json_array:
        _vaule._array = other._vaule._array;
        break;
    case json_object:
        _vaule._object = other._vaule._object;
        break;
    default:
        break;
    }
}
void Json::clear()
{
    switch (_type)
    {
    case json_null:
        break;
    case json_bool:
        _vaule._bool = false;
        break;
    case json_int:
        _vaule._int = 0;
        break;
    case json_double:
        _vaule._double = 0.0;
        break;
    case json_string:
        delete _vaule._string;
        break;
    case json_array:
    {
        for (auto it = _vaule._array->begin(); it != _vaule._array->end(); ++it)
        {
            it->clear();
        }
        delete _vaule._array;
        break;
    }
    case json_object:
    {
        for (auto it = _vaule._object->begin(); it != _vaule._object->end(); ++it)
        {
            (it->second).clear();
        }
        delete _vaule._object;
        break;
    }
    default:
        break;
    }
    _type = json_null;
}

bool Json::operator==(const Json& other) //浅拷贝(效率)
{
    if (_type != other._type)
    {
        return false;
    }
    switch (_type)
    {
    case json_null:
        return true;
    case json_bool:
        return _vaule._bool == other._vaule._bool;
    case json_int:
        return _vaule._int == other._vaule._int;
    case json_double:
        return _vaule._double == other._vaule._double;
    case json_string:
        return *(_vaule._string) == *(other._vaule._string);
    case json_array:
    {
       /*if(_vaule._array->size() != other._vaule._array->size())
       {
           return false;
       }
       for (size_t i = 0; i < _vaule._array->size(); ++i)
       {
           if ((*(_vaule._array))[i] != (* (other._vaule._array))[i])
           {
               return false;
           }
       }
       return true;*/
        return _vaule._array == other._vaule._array;
    }
    case json_object:
    {
        return _vaule._object == other._vaule._object;
    }
    default:
        break;
    }
    return false;
}
bool Json::operator!=(const Json& other)
{
    return !(*this == other);
}
bool Json::asBool() const
{
    if (_type != json_bool)
    {
        throw new std::logic_error("type error,not bool vaule");
    }
    return _vaule._bool;
}
int Json::asInt()const
{
    if (_type != json_int)
    {
        throw new std::logic_error("type error,not int vaule");
    }
    return _vaule._int;
}
double Json::asDouble()const
{
    if (_type != json_double)
    {
        throw new std::logic_error("type error,not double vaule");
    }
    return _vaule._double;
}
std::string Json::asString()const
{
    if (_type != json_string)
    {
        throw new std::logic_error("type error,not string vaule");
    }
    return *(_vaule._string);
}
bool Json::has(int index)
{
    if (_type != json_array)
    {
        return false;
    }
    int size = static_cast<int>((_vaule._array)->size());
    return (index >= 0 && index < size);
}
bool Json::has(const char* key)
{
    string name(key);
    return has(name);
}
bool Json::has(const std::string& key)
{
    if (_type != json_object)
    {
        return false;
    }
    return (_vaule._object)->find(key) != (_vaule._object)->end();
}

void Json::remove(int index)
{
    if (_type != json_array)
    {
        return;
    }
    int size = static_cast<int>((_vaule._array)->size());
    if (index < 0 || index >= size)
    {
        return;
    }
    (_vaule._array)->at(index).clear();
    (_vaule._array)->erase((_vaule._array)->begin() + index);
}
void Json::remove(const char* key)
{
    string name(key);
    return remove(name);
}
void Json::remove(const std::string& key)
{
    auto it = (_vaule._object)->find(key);
    if (it == (_vaule._object)->end())
    {
        return;
    }
    (*(_vaule._object))[key].clear();
    (_vaule._object)->erase(key);
}

void Json::parse(const std::string& str)
{
    Parser p;
    p.load(str);
    *this = p.parse();
}

2.parser模块对json串进行解析

parser模块中用递归的方式处理。

parser.h

#pragma once
#include "json.h"
#include <string>
#include <regex>
namespace yazi
{
    namespace json
    {
        class Parser
        {
        public:
            Parser();
            void load(const std::string& str);
            Json parse();
        private:
            void skip_white_space();
            char get_next_token();
            Json parse_null();
            Json parse_bool();
            Json parse_number();
            std::string parse_string();
            Json parse_array();
            Json parse_object();
        private:
            std::string _str;
            int _index;
        };
    }
}

parser.cc

#include "parser.h"
using namespace yazi::json;
Parser::Parser() : _str(""), _index(0)
{
}
void Parser::load(const std::string& str)
{
    _str = str;
    _index = 0;
}
Json Parser::parse()
{
    char ch = get_next_token();
    switch (ch)
    {
    case 'n':
        --_index;
        return parse_null();
    case 't':
    case 'f':
        --_index;
        return parse_bool();
    case '-':
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
        --_index;
        return parse_number();
    case '"':
        return Json(parse_string());
    case '[':
        return parse_array();
    case '{':
        return parse_object();
    default:
        break;
    }
    throw new std::logic_error("unexpected char");
}
void Parser::skip_white_space()
{
    while (_str[_index] == ' ' || _str[_index] == '\n' || _str[_index] == '\r' || _str[_index] == '\t')
    {
        ++_index;
    }
}
char Parser::get_next_token()
{
    skip_white_space();
    return _str[_index++];
}
Json Parser::parse_null()
{
    if (_str.compare(_index, 4, "null") == 0)
    {
        _index += 4;
        return Json();
    }
    throw new std::logic_error("parse null error");
}
Json Parser::parse_bool()
{
    if (_str.compare(_index, 4, "true") == 0)
    {
        _index += 4;
        return Json(true);
    }
    else if (_str.compare(_index, 5, "false") == 0)
    {
        _index += 5;
        return Json(false);
    }
    else
    {
        throw new std::logic_error("parse bool error");
    }
}
Json Parser::parse_number()
{
    int pos = _index;
    if (_str[_index] == '-')
    {
        ++_index;
    }
    if (isdigit(_str[_index]) == 0)
    {
        throw new std::logic_error("parse number error");
    }
    while (isdigit(_str[_index]) != 0)
    {
        ++_index;
    }
    if (_str[_index] != '.')
    {
        int i = std::atoi(_str.c_str() + pos);
        return Json(std::move(i));
    }
    if (isdigit(_str[++_index]) == 0)
    {
        throw new std::logic_error("parse number error");
    }
    while (isdigit(_str[_index]) != 0)
    {
        ++_index;
    }
    double f = std::atof(_str.c_str() + pos);
    return Json(std::move(f));
}
std::string Parser::parse_string()
{
    std::string out;
    while (true)
    {
        char ch = _str[_index++];
        if (ch == '"')
        {
            break;
        }
        if (ch == '\\')
        {
            ch = _str[_index++];
            switch (ch)
            {
            case '\n':
                out += '\n';
                break;
            case '\r':
                out += '\r';
                break;
            case '\t':
                out += '\t';
                break;
            case '\b':
                out += '\b';
                break;
            case '\f':
                out += '\f';
                break;
            case '"':
                out += "\\\"";
                break;
            case '\\':
                out += "\\\\";
                break;
            case 'u':
                out += "\\u";
                for (int i = 0; i < 4; ++i)
                {
                    out += _str[_index++];
                }
                break;
            default:
                break;
            }
        }
        else
        {
            out += ch;
        }
    }
    return std::move(out);
}
Json Parser::parse_array()
{
    Json arr(Json::json_array);
    char ch = get_next_token();
    if (ch == ']')
    {
        return arr;
    }
    --_index;
    while (true)
    {
        arr.append(parse());   //递归解析
        ch = get_next_token();
        if (ch == ']')
        {
            break;
        }
        if (ch != ',')
        {
            throw new std::logic_error("parse array error");
        }
        //++_index;//ERROR
    }
    return arr;
}
Json Parser::parse_object()
{
    Json obj(Json::json_object);
    char ch = get_next_token();
    if(ch == '}')
    {
        return obj;
    }
    --_index;
    while(true)
    {
        ch = get_next_token();
        if(ch != '"')
        {
            throw new std::logic_error("parse object error");
        }
        std::string key = parse_string();
        ch = get_next_token();
        if(ch != ':')
        {
            throw new std::logic_error("parse object error");
        }
        obj[key] = parse();
        ch = get_next_token();
        if(ch == '}')
        {
            break;
        }
        if(ch != ',')
        {
            throw new std::logic_error("parse object error");
        }
        //++_index;//ERROR
    }
    return obj;
}

main.cc

#include <iostream>
using namespace std;


#include "json/json.h"
using namespace yazi::json;
#include <fstream>
void Test1(void)
{
    const std::string& str = "[1, \"a\", 3, null, -1.2345, true, false, \"hello world\"]";
    Json v;
    v.parse(str);
    std::cout << v.str() << std::endl;
}
void Test2(void)
{
    const std::string& str = "{\"a\":true,\"b\":{\"a\":true,\"b\":[1, \"a\", 3, null, -1.2345, true, false, \"hello world\"],\"c\":123,\"4\":\"hello world\"},\"c\":123,\"4\":\"hello world\"}";
    Json v;
    v.parse(str);
    std::cout << v.str() << std::endl;
}
void Test3()
{
    ifstream in("./json_test");
    stringstream ss;
    ss << in.rdbuf();
    const std::string& str = ss.str();
    //std::cout << str << std::endl;
     Json v;
     v.parse(str);
     //std::cout << v.str() << std::endl;
    std::cout << v["data"]["search_data"][0]["elements"][0]["name"].str() << std::endl;
}
int main()
{
    Test3();
    //Test2();
    //Test1();

    // Json v1;
    // Json v2 = true;
    // Json v3 = 123;
    // Json v4 = 1.23;
    // Json v5 = "hello";
    // bool b = v2;
    // int i = v3;
    // double f = v4;
    // const std::string& s = v5;
    // cout << b  << " " << i <<" "  << f << " "  << s << endl;

    //  Json arr;
    //  arr[1] = true;
    //  arr[2] = 123;
    //  arr[3] = 1.23;
    //  arr[4] = "hello";
    //  /*std::cout << arr.has(0) << std::endl;
    //  std::cout << arr.has(4) << std::endl;*/
     
    //  Json obj;
    //  obj["bool"] = true;
    //  obj["int"] = 123;
    //  obj["double"] = 1.23;
    //  obj["arr"] = arr;
    //  std::cout << obj.str() << std::endl;
    //  obj.clear();
}

makefile

main:main.cc ./json/json.cc ./json/parser.cc
	g++ -o $@ $^ -std=c++14
.PHONY:clean
clean:
	rm -rf main

json_test(用来测试)

{
    "status": 0,
    "message": "",
    "data": {
        "search_data": [
            {
                "elements": [
                    {
                        "rating": 0,
                        "name": "奈良市",
                        "url": "/scenic/3/10052/",
                        "wish_to_go_count": 328,
                        "name_orig": "奈良市",
                        "visited_count": 1958,
                        "comments_count": 0,
                        "location": {
                            "lat": 34.685087,
                            "lng": 135.805
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "奈良市",
                        "name_en": "Nara",
                        "type": 3,
                        "id": 10052,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "小樽市",
                        "url": "/scenic/3/26772/",
                        "wish_to_go_count": 266,
                        "name_orig": "小樽市",
                        "visited_count": 954,
                        "comments_count": 0,
                        "location": {
                            "lat": 43.190717,
                            "lng": 140.994662
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "小樽市",
                        "name_en": "Otaru",
                        "type": 3,
                        "id": 26772,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "槟城",
                        "url": "/scenic/2/8257/",
                        "wish_to_go_count": 93,
                        "name_orig": "槟城",
                        "visited_count": 849,
                        "comments_count": 0,
                        "location": {
                            "lat": 5.414167,
                            "lng": 100.328759
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "槟城",
                        "name_en": "Penang",
                        "type": 2,
                        "id": 8257,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/province.png"
                    },
                    {
                        "rating": 0,
                        "name": "墨尔本",
                        "url": "/scenic/3/47810/",
                        "wish_to_go_count": 2927,
                        "name_orig": "墨尔本",
                        "visited_count": 2112,
                        "comments_count": 0,
                        "location": {
                            "lat": -37.814216,
                            "lng": 144.963231
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "墨尔本",
                        "name_en": "Melbourne",
                        "type": 3,
                        "id": 47810,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "广岛县",
                        "url": "/scenic/2/9474/",
                        "wish_to_go_count": 36,
                        "name_orig": "广岛县",
                        "visited_count": 160,
                        "comments_count": 0,
                        "location": {
                            "lat": 34.39656,
                            "lng": 132.459622
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "广岛县",
                        "name_en": "Hiroshima Prefecture",
                        "type": 2,
                        "id": 9474,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/province.png"
                    },
                    {
                        "rating": 0,
                        "name": "泰国",
                        "url": "/scenic/1/3649/",
                        "wish_to_go_count": 22131,
                        "name_orig": "泰国",
                        "visited_count": 22298,
                        "comments_count": 0,
                        "location": {
                            "lat": 15.870032,
                            "lng": 100.992541
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": "TH",
                        "has_route_maps": false,
                        "rating_users": 0
                    },
                    {
                        "rating": 0,
                        "name": "芬兰",
                        "url": "/scenic/1/3613/",
                        "wish_to_go_count": 665,
                        "name_orig": "芬兰",
                        "visited_count": 1058,
                        "comments_count": 0,
                        "location": {
                            "lat": 61.92411,
                            "lng": 25.748151
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": "FI",
                        "has_route_maps": false,
                        "rating_users": 0
                    },
                    {
                        "rating": 0,
                        "name": "美国",
                        "url": "/scenic/1/3803/",
                        "wish_to_go_count": 8828,
                        "name_orig": "美国",
                        "visited_count": 12967,
                        "comments_count": 0,
                        "location": {
                            "lat": 37.09024,
                            "lng": -95.712891
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": "US",
                        "has_route_maps": false,
                        "rating_users": 0
                    },
                    {
                        "rating": 0,
                        "name": "马来西亚",
                        "url": "/scenic/1/3676/",
                        "wish_to_go_count": 6339,
                        "name_orig": "马来西亚",
                        "visited_count": 9533,
                        "comments_count": 0,
                        "location": {
                            "lat": 4.210484,
                            "lng": 101.975766
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": "MY",
                        "has_route_maps": false,
                        "rating_users": 0
                    },
                    {
                        "rating": 0,
                        "name": "意大利",
                        "url": "/scenic/1/3720/",
                        "wish_to_go_count": 7689,
                        "name_orig": "意大利",
                        "visited_count": 6508,
                        "comments_count": 0,
                        "location": {
                            "lat": 41.87194,
                            "lng": 12.56738
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": "IT",
                        "has_route_maps": false,
                        "rating_users": 0
                    },
                    {
                        "rating": 0,
                        "name": "新加坡",
                        "url": "/scenic/1/3589/",
                        "wish_to_go_count": 5847,
                        "name_orig": "新加坡",
                        "visited_count": 7835,
                        "comments_count": 0,
                        "location": {
                            "lat": 1.352083,
                            "lng": 103.819836
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": "SG",
                        "has_route_maps": false,
                        "rating_users": 0
                    },
                    {
                        "rating": 0,
                        "name": "挪威",
                        "url": "/scenic/1/3258/",
                        "wish_to_go_count": 788,
                        "name_orig": "挪威",
                        "visited_count": 850,
                        "comments_count": 0,
                        "location": {
                            "lat": 60.472024,
                            "lng": 8.468946
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": "NO",
                        "has_route_maps": false,
                        "rating_users": 0
                    }
                ],
                "type": "destination",
                "title": "国外热门目的地"
            },
            {
                "elements": [
                    {
                        "rating": 0,
                        "name": "台湾",
                        "url": "/scenic/1/3660/",
                        "wish_to_go_count": 37947,
                        "name_orig": "台湾",
                        "visited_count": 15729,
                        "comments_count": 0,
                        "location": {
                            "lat": 23.69781,
                            "lng": 120.960515
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": "TW",
                        "has_route_maps": false,
                        "rating_users": 0
                    },
                    {
                        "rating": 0,
                        "name": "香港",
                        "url": "/scenic/1/3814/",
                        "wish_to_go_count": 23495,
                        "name_orig": "香港",
                        "visited_count": 31249,
                        "comments_count": 0,
                        "location": {
                            "lat": 22.396428,
                            "lng": 114.109497
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": "HK",
                        "has_route_maps": true,
                        "rating_users": 0
                    },
                    {
                        "rating": 0,
                        "name": "厦门",
                        "url": "/scenic/3/65012/",
                        "wish_to_go_count": 29887,
                        "name_orig": "厦门",
                        "visited_count": 26077,
                        "comments_count": 0,
                        "location": {
                            "lat": 24.477188,
                            "lng": 118.094398
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "厦门",
                        "name_en": "Xiamen",
                        "type": 3,
                        "id": 65012,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "北京",
                        "url": "/scenic/3/8248/",
                        "wish_to_go_count": 7118,
                        "name_orig": "北京",
                        "visited_count": 53416,
                        "comments_count": 0,
                        "location": {
                            "lat": 39.90561,
                            "lng": 116.413634
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "北京",
                        "name_en": "Beijing",
                        "type": 3,
                        "id": 8248,
                        "has_route_maps": true,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "丽江市",
                        "url": "/scenic/3/65362/",
                        "wish_to_go_count": 27368,
                        "name_orig": "丽江市",
                        "visited_count": 19389,
                        "comments_count": 0,
                        "location": {
                            "lat": 26.851553,
                            "lng": 100.228931
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "丽江市",
                        "name_en": "Lijiang",
                        "type": 3,
                        "id": 65362,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "成都",
                        "url": "/scenic/3/14209/",
                        "wish_to_go_count": 14464,
                        "name_orig": "成都",
                        "visited_count": 23484,
                        "comments_count": 0,
                        "location": {
                            "lat": 30.569858,
                            "lng": 104.069084
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "成都",
                        "name_en": "Chengdu",
                        "type": 3,
                        "id": 14209,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "上海",
                        "url": "/scenic/3/13961/",
                        "wish_to_go_count": 7601,
                        "name_orig": "上海",
                        "visited_count": 46500,
                        "comments_count": 0,
                        "location": {
                            "lat": 31.228402,
                            "lng": 121.478143
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "上海",
                        "name_en": "Shanghai",
                        "type": 3,
                        "id": 13961,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "拉萨",
                        "url": "/scenic/3/5249/",
                        "wish_to_go_count": 15492,
                        "name_orig": "拉萨",
                        "visited_count": 6544,
                        "comments_count": 0,
                        "location": {
                            "lat": 29.649671,
                            "lng": 91.173526
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "拉萨",
                        "name_en": "Lhasa",
                        "type": 3,
                        "id": 5249,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "大理",
                        "url": "/scenic/3/43908/",
                        "wish_to_go_count": 10103,
                        "name_orig": "大理",
                        "visited_count": 13291,
                        "comments_count": 0,
                        "location": {
                            "lat": 25.603496,
                            "lng": 100.268781
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "大理",
                        "name_en": "Dali",
                        "type": 3,
                        "id": 43908,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "三亚",
                        "url": "/scenic/3/65557/",
                        "wish_to_go_count": 8951,
                        "name_orig": "三亚",
                        "visited_count": 11920,
                        "comments_count": 0,
                        "location": {
                            "lat": 18.251176,
                            "lng": 109.51604
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "三亚",
                        "name_en": "Sanya",
                        "type": 3,
                        "id": 65557,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    }
                ],
                "type": "destination",
                "title": "国内热门目的地"
            }
        ],
        "date_time": "2017-09-11 10:52:27.811321",
        "elements": [
            {
                "type": 1,
                "data": [
                    [
                        {
                            "platform": "android",
                            "image_url": "http://photos.breadtrip.com/covers_2017_09_05_d5b225291045767fcfa0508f3d96ae26.jpg?imageView/2/w/960/",
                            "html_url": "http://www.iqiyi.com/v_19rr8w7drg.html?dummy=&wx_uid2=wxidoG0a9jsIGfq1jln1HtWebMCOKKSQ"
                        },
                        {
                            "platform": "android",
                            "image_url": "http://photos.breadtrip.com/covers_2014_12_25_ed43331bac65ee0752f7e56116993b2c.jpg?imageView2/2/w/750/format/jpg/interlace/1/",
                            "html_url": "http://web.breadtrip.com/mobile/destination/topic/2387718817/"
                        },
                        {
                            "platform": "android",
                            "image_url": "http://photos.breadtrip.com/covers_2014_10_29_46217a91ace672787ed1fec4c2011b52.png?imageView2/2/w/750/format/jpg/interlace/1/",
                            "html_url": "http://web.breadtrip.com/mobile/destination/topic/2387718790/"
                        },
                        {
                            "platform": "android",
                            "image_url": "http://photos.breadtrip.com/covers_2015_04_24_59b10571419fb3888224d83365f561e8.jpg?imageView2/2/w/750/format/jpg/interlace/1/",
                            "html_url": "http://web.breadtrip.com/mobile/destination/topic/2387718734/"
                        },
                        {
                            "platform": "android",
                            "image_url": "http://photos.breadtrip.com/covers_2014_12_05_c9aea564f43b673ea6d8dcf9c6c4627b.jpg?imageView2/2/w/750/format/jpg/interlace/1/",
                            "html_url": "http://web.breadtrip.com/mobile/destination/topic/2387718810/"
                        },
                        {
                            "platform": "android",
                            "image_url": "http://photos.breadtrip.com/covers_2016_02_26_51987e2bebba67bad75ccb114dfea7ab.png?imageView2/2/w/750/format/jpg/interlace/1/",
                            "html_url": "http://web.breadtrip.com/mobile/destination/topic/2387719110/"
                        }
                    ]
                ],
                "desc": "广告banner"
            },
            {
                "type": 11,
                "data": [
                    {
                        "title": "每日精选故事"
                    }
                ],
                "desc": ""
            },
            {
                "type": 10,
                "data": [
                    {
                        "text": "halo 雷猴嘛\n我猜你是个妹纸\n我猜你是个爱美的妹纸\n我猜你是个喜欢首饰and爱美的妹纸\n我猜你是个喜欢手作首饰and爱美的妹纸\n我猜…你是个亲手做首饰给女票的汉纸!\n\n\n\n我是个喜欢手工喜欢首饰喜欢发现美的美男纸,来吃我一安利呗!",
                        "is_liked": false,
                        "index_cover": "http://photos.breadtrip.com/photo_d_2016_08_02_dca0659576dfe60382943612e2fff308ff2b1f1d56055e6b29f6fdd317f3ff8c.jpeg?imageView/2/w/960/q/85",
                        "poi": {},
                        "cover_image_height": 1206,
                        "trip_id": 2387270842,
                        "index_title": "",
                        "center_point": {
                            "lat": 0,
                            "lng": 0
                        },
                        "view_count": 45446,
                        "location_alias": "Dream High梦想社",
                        "cover_image_1600": "http://photos.breadtrip.com/photo_d_2016_08_02_09931d012facf6186f9c25202983dcaa68efddaccb4cbc0e78a0ded46afb778e.jpeg?imageView/2/w/1384/h/1384/q/85",
                        "cover_image_s": "http://photos.breadtrip.com/photo_d_2016_08_02_09931d012facf6186f9c25202983dcaa68efddaccb4cbc0e78a0ded46afb778e.jpeg?imageView/1/w/280/h/280/q/75",
                        "share_url": "btrip/spot/2387867495/",
                        "timezone": "Asia/Shanghai",
                        "date_tour": "2016-07-31T20:49:00+08:00",
                        "is_hiding_location": true,
                        "user": {
                            "location_name": "广东_广州",
                            "name": "林酷儿",
                            "resident_city_id": 275,
                            "mobile": "",
                            "gender": 2,
                            "avatar_m": "http://photos.breadtrip.com/avatar_17_c1_1214298920959e94700b4cb370271320c5745e6c.jpg-avatar.m",
                            "cover": "http://photos.breadtrip.com/default_user_cover_06.jpg-usercover.display",
                            "custom_url": "",
                            "experience": {
                                "value": 101,
                                "level_info": {
                                    "name": "",
                                    "value": 2
                                }
                            },
                            "id": 2384430044,
                            "birthday": "",
                            "country_num": null,
                            "avatar_s": "http://photos.breadtrip.com/avatar_17_c1_1214298920959e94700b4cb370271320c5745e6c.jpg-avatar.s",
                            "country_code": null,
                            "email_verified": false,
                            "is_hunter": false,
                            "cdc2": false,
                            "avatar_l": "http://photos.breadtrip.com/avatar_17_c1_1214298920959e94700b4cb370271320c5745e6c.jpg-avatar.l",
                            "email": "",
                            "user_desc": "",
                            "points": 26
                        },
                        "spot_id": 2387867495,
                        "is_author": false,
                        "cover_image_w640": "http://photos.breadtrip.com/photo_d_2016_08_02_09931d012facf6186f9c25202983dcaa68efddaccb4cbc0e78a0ded46afb778e.jpeg?imageView/1/w/640/h/480/q/85",
                        "region": {
                            "primary": "",
                            "secondary": ""
                        },
                        "comments_count": 9,
                        "cover_image": "http://photos.breadtrip.com/photo_d_2016_08_02_09931d012facf6186f9c25202983dcaa68efddaccb4cbc0e78a0ded46afb778e.jpeg?imageView/2/w/960/q/85",
                        "cover_image_width": 1600,
                        "recommendations_count": 22
                    }
                ],
                "desc": ""
            },
            {
                "type": 10,
                "data": [
                    {
                        "text": "挑战极限和心跳,让自己成为一个有趣的人。\n2016月5月在面包旅行,偶然下兼职做一个猎人哈哈(活动名字上帝之眼),感觉挺酷的。\n重庆最具特色的,当然是城市里最耀眼的高楼夜景,曾经有一部电影“重庆森林”,故事很多场景,以及城市展现出重庆这座奇葩一样的城市,独具特色话3D话,很多电影都有在重庆取景。",
                        "is_liked": false,
                        "index_cover": "http://photos.breadtrip.com/photo_d_2016_06_24_4bc9f811fa5b900762fb1d55dff164f32066a28d4010bf9f4a4c20dd62634b4d.jpg?imageView/2/w/960/q/85",
                        "poi": {
                            "tel": "023-62872299",
                            "currency": "CNY",
                            "is_nearby": true,
                            "timezone": "Asia/Chongqing",
                            "id": 2387458620,
                            "category": 11,
                            "recommended_reason": "看滚滚江水向东流去,犹如有登高望远",
                            "fee": "免费",
                            "spot_region": "重庆",
                            "date_added": "2014-12-16 10:48:55",
                            "time_consuming_max": 0,
                            "time_consuming": null,
                            "extra1": "",
                            "recommended": true,
                            "location": {
                                "lat": 29.554926,
                                "lng": 106.586696
                            },
                            "opening_time": "全天",
                            "type": 5,
                            "time_consuming_min": 0,
                            "website": "",
                            "description": "长江索道起于渝中区长安寺,横跨长江至南岸区上新街。乘坐过江索道,除了可以欣赏两江美景外,还可以从索道上俯瞰洪崖洞、湖广会馆、南滨路等著名景观。",
                            "arrival_type": "乘105、132、135、153、181、261、0321夜班、476、0491夜班、0492夜班、0493夜班、871、898路等公交车在新华路站下车即到",
                            "address": "重庆市渝中区新华路153号",
                            "verified": true,
                            "name_en": "",
                            "icon": "http://media.breadtrip.com/images/icons/poi_category_11.png",
                            "name": "长江索道",
                            "popularity": 809
                        },
                        "cover_image_height": 1067,
                        "trip_id": 2387276098,
                        "index_title": "",
                        "center_point": {
                            "lat": 0,
                            "lng": 0
                        },
                        "view_count": 49744,
                        "location_alias": "",
                        "cover_image_1600": "http://photos.breadtrip.com/photo_d_2016_06_24_7df54edb43492917e7d1cb743a4a379b92bc85c2562bb6b1a39d346c4f6fc0e9.jpg?imageView/2/w/1384/h/1384/q/85",
                        "cover_image_s": "http://photos.breadtrip.com/photo_d_2016_06_24_7df54edb43492917e7d1cb743a4a379b92bc85c2562bb6b1a39d346c4f6fc0e9.jpg?imageView/1/w/280/h/280/q/75",
                        "share_url": "btrip/spot/2387843168/",
                        "timezone": "Asia/Shanghai",
                        "date_tour": "2016-06-24T10:51:14+08:00",
                        "is_hiding_location": false,
                        "user": {
                            "location_name": "",
                            "name": "W猫小北",
                            "resident_city_id": 288652,
                            "mobile": "",
                            "gender": 1,
                            "avatar_m": "http://photos.breadtrip.com/avatar_bc_fd_a6720f5e50d1f22194c51f73329f0e9c48ab7ba8.jpg-avatar.m",
                            "cover": "http://photos.breadtrip.com/default_user_cover_05.jpg-usercover.display",
                            "custom_url": "",
                            "experience": {
                                "value": 1242,
                                "level_info": {
                                    "name": "",
                                    "value": 4
                                }
                            },
                            "id": 2387577484,
                            "birthday": "",
                            "country_num": "86",
                            "avatar_s": "http://photos.breadtrip.com/avatar_bc_fd_a6720f5e50d1f22194c51f73329f0e9c48ab7ba8.jpg-avatar.s",
                            "country_code": "CN",
                            "email_verified": false,
                            "is_hunter": true,
                            "cdc2": false,
                            "avatar_l": "http://photos.breadtrip.com/avatar_bc_fd_a6720f5e50d1f22194c51f73329f0e9c48ab7ba8.jpg-avatar.l",
                            "email": "",
                            "user_desc": "我是猫小北,喜欢摄影摄像以及美食旅行,独自旅行大半中国,特长就是长得帅,吃得多还不胖。喜欢用心记录不容易发现的美好,我想记录这一切的美好。",
                            "points": 87
                        },
                        "spot_id": 2387843168,
                        "is_author": false,
                        "cover_image_w640": "http://photos.breadtrip.com/photo_d_2016_06_24_7df54edb43492917e7d1cb743a4a379b92bc85c2562bb6b1a39d346c4f6fc0e9.jpg?imageView/1/w/640/h/480/q/85",
                        "region": {
                            "primary": "",
                            "secondary": ""
                        },
                        "comments_count": 7,
                        "cover_image": "http://photos.breadtrip.com/photo_d_2016_06_24_7df54edb43492917e7d1cb743a4a379b92bc85c2562bb6b1a39d346c4f6fc0e9.jpg?imageView/2/w/960/q/85",
                        "cover_image_width": 1600,
                        "recommendations_count": 40
                    }
                ],
                "desc": ""
            },
            {
                "type": 10,
                "data": [
                    {
                        "text": "很有幸能有王老这样的人让我们能睹旧物思旧人旧事,陈列室虽不大,却也充斥了老北京饮食医用居的方方面面,可以亲手触摸历史,了解自己现在工作城市的过去现在让人倍感亲切!",
                        "is_liked": false,
                        "index_cover": "http://photos.breadtrip.com/photo_d_2016_06_09_23_56_51_174_123986672_-1220261189.jpg?imageView/2/w/960/q/85",
                        "poi": "",
                        "cover_image_height": 724,
                        "trip_id": 2387247307,
                        "index_title": "",
                        "center_point": {},
                        "view_count": 39166,
                        "location_alias": "",
                        "cover_image_1600": "http://photos.breadtrip.com/photo_d_2016_06_09_23_56_50_703_123986672_834948024.jpg?imageView/2/w/1384/h/1384/q/85",
                        "cover_image_s": "http://photos.breadtrip.com/photo_d_2016_06_09_23_56_50_703_123986672_834948024.jpg?imageView/1/w/280/h/280/q/75",
                        "share_url": "btrip/spot/2387849028/",
                        "timezone": "Asia/Shanghai",
                        "date_tour": "2016-06-09T23:42:30+08:00",
                        "is_hiding_location": false,
                        "user": {
                            "location_name": "",
                            "name": "Lucy鱼er",
                            "resident_city_id": "",
                            "mobile": "",
                            "gender": 2,
                            "avatar_m": "http://photos.breadtrip.com/avatar_d0_f2_9450f59011820dcdfe7f0317d76f7fb0654cf52c.jpg-avatar.m",
                            "cover": "http://media.breadtrip.com/user_covers/default/cover_3.jpg",
                            "custom_url": "",
                            "experience": {
                                "value": 132,
                                "level_info": {
                                    "name": "",
                                    "value": 2
                                }
                            },
                            "id": 2386840189,
                            "birthday": "",
                            "country_num": null,
                            "avatar_s": "http://photos.breadtrip.com/avatar_d0_f2_9450f59011820dcdfe7f0317d76f7fb0654cf52c.jpg-avatar.s",
                            "country_code": null,
                            "email_verified": false,
                            "is_hunter": false,
                            "cdc2": false,
                            "avatar_l": "http://photos.breadtrip.com/avatar_d0_f2_9450f59011820dcdfe7f0317d76f7fb0654cf52c.jpg-avatar.l",
                            "email": "",
                            "user_desc": "",
                            "points": 52
                        },
                        "spot_id": 2387849028,
                        "is_author": false,
                        "cover_image_w640": "http://photos.breadtrip.com/photo_d_2016_06_09_23_56_50_703_123986672_834948024.jpg?imageView/1/w/640/h/480/q/85",
                        "region": {
                            "primary": "",
                            "secondary": ""
                        },
                        "comments_count": 2,
                        "cover_image": "http://photos.breadtrip.com/photo_d_2016_06_09_23_56_50_703_123986672_834948024.jpg?imageView/2/w/960/q/85",
                        "cover_image_width": 965,
                        "recommendations_count": 13
                    }
                ],
                "desc": ""
            },
            {
                "type": 10,
                "data": [
                    {
                        "text": "献给爱我们的女神",
                        "is_liked": false,
                        "index_cover": "http://photos.breadtrip.com/photo_d_2016_06_19_01_21_20_989_123986672_17737936936133063098.jpg?imageView/2/w/960/q/85",
                        "poi": "",
                        "cover_image_height": 816,
                        "trip_id": 2387282916,
                        "index_title": "",
                        "center_point": {},
                        "view_count": 36207,
                        "location_alias": "",
                        "cover_image_1600": "http://photos.breadtrip.com/photo_d_2016_06_19_01_21_20_926_123986672_17737936923172662193.jpg?imageView/2/w/1384/h/1384/q/85",
                        "cover_image_s": "http://photos.breadtrip.com/photo_d_2016_06_19_01_21_20_926_123986672_17737936923172662193.jpg?imageView/1/w/280/h/280/q/75",
                        "share_url": "btrip/spot/2387842143/",
                        "timezone": "Asia/Shanghai",
                        "date_tour": "2016-06-19T01:19:07+08:00",
                        "is_hiding_location": false,
                        "user": {
                            "location_name": "",
                            "name": "丑到没墙角",
                            "resident_city_id": "",
                            "mobile": "",
                            "gender": 2,
                            "avatar_m": "http://photos.breadtrip.com/avatar_41_b8_aedfd71640e3ec09d0c30edc47df04dc56dbf38a.jpg-avatar.m",
                            "cover": "http://photos.breadtrip.com/default_user_cover_10.jpg-usercover.display",
                            "custom_url": "",
                            "experience": {
                                "value": 59,
                                "level_info": {
                                    "name": "",
                                    "value": 1
                                }
                            },
                            "id": 2384288641,
                            "birthday": "",
                            "country_num": null,
                            "avatar_s": "http://photos.breadtrip.com/avatar_41_b8_aedfd71640e3ec09d0c30edc47df04dc56dbf38a.jpg-avatar.s",
                            "country_code": null,
                            "email_verified": false,
                            "is_hunter": false,
                            "cdc2": false,
                            "avatar_l": "http://photos.breadtrip.com/avatar_41_b8_aedfd71640e3ec09d0c30edc47df04dc56dbf38a.jpg-avatar.l",
                            "email": "",
                            "user_desc": "",
                            "points": 2
                        },
                        "spot_id": 2387842143,
                        "is_author": false,
                        "cover_image_w640": "http://photos.breadtrip.com/photo_d_2016_06_19_01_21_20_926_123986672_17737936923172662193.jpg?imageView/1/w/640/h/480/q/85",
                        "region": {
                            "primary": "",
                            "secondary": ""
                        },
                        "comments_count": 2,
                        "cover_image": "http://photos.breadtrip.com/photo_d_2016_06_19_01_21_20_926_123986672_17737936923172662193.jpg?imageView/2/w/960/q/85",
                        "cover_image_width": 1088,
                        "recommendations_count": 21
                    }
                ],
                "desc": ""
            },
            {
                "type": 9,
                "data": [
                    {
                        "title": "精彩原创和专题"
                    }
                ],
                "desc": ""
            },
            {
                "type": 4,
                "data": [
                    {
                        "cover_image_default": "http://photos.breadtrip.com/photo_2017_07_18_0996aaecaadfdc9ed3534ed9b0c4928c.jpg?imageView/2/w/960/q/85",
                        "waypoints": 153,
                        "wifi_sync": false,
                        "last_day": "2017-06-14",
                        "id": 2387425140,
                        "view_count": 25191,
                        "privacy": 0,
                        "day_count": 7,
                        "index_title": "荷兰--黄金时代的回响"
                    }
                ]
            }
        ]
    }
}

 相关测试截图:

 

 

 

该工具设计有缺陷,后期可以更改位策略模式,对json类进行抽象。API设计不够完善后期可以根据需求自行增加接口。Json类中对字符串,数组和对象只进行了浅拷贝(为了效率)后期可以改成深拷贝,浅拷贝没有设计析构的接口,json类只能释放一次,不能重复释放。

githup地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值