zoukankan      html  css  js  c++  java
  • C++编写json生成器

    使用C++来编写json生成器的使用来熟悉C++区别于C的使用方法和语法。

    头文件

    /*
    json-writer.cpp
    */
    
    #ifndef _JSONWRITER_H_
    #define _JSONWRITER_H_
    
    #include<iostream>
    #include<string>
    #include<stack>
    #include<cstdint>
    using namespace std;
    
    class JsonWriter
    {
        public:
            enum ContainerType
            {
                CONTAINER_TYPE_ARRAY,
                CONTAINER_TYPE_OBJECT
            };
    
            enum ContainerLayout
            {
                CONTAINER_LAYOUT_INHERIT,
                CONTAINER_LAYOUT_MULTI_LINE,
                CONTAINER_LAYOUT_SINGLE_LINE
            };
    
            explicit JsonWriter():
                writer(NULL),
                initialIndentDepth(0),
                indent("  "),
                containerPadding(" "),
                keyPaddingLeft(""),
                keyPaddingRight(" "),
                defaultContainerLayout(CONTAINER_LAYOUT_MULTI_LINE),
                forceDefaultContainerLayout(false)
                {
    
                }
            
            void ConfigureCompressedOutput()
            {
                SetIndent ("");
                SetContainerPadding("");
                SetKeyPaddingLeft("");
                SetKeyPaddingRight("");
                SetDefaultContainerLayout(CONTAINER_LAYOUT_MULTI_LINE);
                SetForceDefaultContainerLayout(true);
            }
    
            ostream *GetWriter() {return writer; }
            void SetWriter (ostream *writer)
            {
                this->writer = writer;
            }
    
            int GetInitialIndentDepth()
            {
                return initialIndentDepth;
            }
            void SetInitialIndentDepth(int depth)
            {
                initialIndentDepth = depth;
            }
    
            const char *GetIndent()
            {
                return indent;
            }
            void SetIndent(const char *indent)
            {
                this->indent = indent;
            }
    
            const char *GetContainerPadding()
            {
                return containerPadding;
            }
            void SetContainerPadding(const char *padding)
            {
                keyPaddingRight = padding;
            }
    
            const char *GetKeyPaddingLeft()
            {
                return keyPaddingLeft;
            }
            void SetKeyPaddingLeft(const char *padding)
            {
                keyPaddingLeft = padding;
            }
    
            const char *GetKeyPaddingRight()
            {
                return keyPaddingRight;
            }
            void SetKeyPaddingRight(const char *padding)
            {
                keyPaddingRight = padding;
            }
    
            ContainerLayout GetDefaultContainerLayout()
            {
                return defaultContainerLayout;
            }
            void SetDefaultContainerLayout(ContainerLayout layout)
            {
                defaultContainerLayout = layout;
            }
    
            bool GetForceDeafultContainerLayout()
            {
                return forceDefaultContainerLayout;
            }
            void SetForceDefaultContainerLayout(bool force)
            {
                forceDefaultContainerLayout = force;
            }
    
            std::ostream& Write()
            {
                if (writer == NULL)
                {
                    return std::cout;
                }
                return *writer;
            }
    
            void WriteEscapedChar (char c);
            void WriteString(const char *str);
    
            void StartChild (bool isKey);
            void StartChild()
            {
                StartChild (false);
            }
    
            void StartContainer(ContainerType type, ContainerLayout layout);
            void EndContainer();
    
            void StartArray()
            {
                StartContainer(CONTAINER_TYPE_ARRAY, CONTAINER_LAYOUT_INHERIT);
            }
            void StartArray(ContainerLayout layout)
            {
                StartContainer(CONTAINER_TYPE_ARRAY, layout);
            }
            void StartShortArray()
            {
                StartContainer(CONTAINER_TYPE_ARRAY, CONTAINER_LAYOUT_SINGLE_LINE);
            }
            void EndArray()
            {
                EndContainer();
            }
    
            void StartObject()
            {
                StartContainer(CONTAINER_TYPE_OBJECT, CONTAINER_LAYOUT_INHERIT);
            }
            void StartObject(ContainerLayout layout)
            {
                StartContainer(CONTAINER_TYPE_OBJECT, layout);
            }
            void StartShortObject()
            {
                StartContainer (CONTAINER_TYPE_OBJECT, CONTAINER_LAYOUT_SINGLE_LINE);
            }
            void EndObjct()
            {
                EndContainer();
            }
    
            void Key(const char *key);
    
            void NullValue();
            void Value(const char *value);
            void Value(std::string value);
            void Value(bool value);
    
            #define VALUE_DEF(t) void Value (t value) {StartChild(); Write() << value; }
            #define KEYVALUE_DEF(t) void KeyValue (const char *key, t value) { Key (key); Value (value); }
    
            VALUE_DEF(int8_t)
            VALUE_DEF(uint8_t)
            VALUE_DEF(int16_t)
            VALUE_DEF(uint16_t)
            VALUE_DEF(int32_t)
            VALUE_DEF(uint32_t)
            VALUE_DEF(int64_t)
            VALUE_DEF(uint64_t)
            VALUE_DEF(float)
            VALUE_DEF(double)
    
            void KeyNullValue( const char *key)
            {
                Key (key);
                NullValue();
            }
    
            KEYVALUE_DEF(const char *)
            KEYVALUE_DEF(std::string)
            KEYVALUE_DEF(bool)
            KEYVALUE_DEF(int8_t)
            KEYVALUE_DEF(uint8_t)
            KEYVALUE_DEF(int16_t)
            KEYVALUE_DEF(uint16_t)
            KEYVALUE_DEF(int32_t)
            KEYVALUE_DEF(uint32_t)
            KEYVALUE_DEF(int64_t)
            KEYVALUE_DEF(uint64_t)
            KEYVALUE_DEF(float)
            KEYVALUE_DEF(double)
    
        private:
            ostream *writer;
            int initialIndentDepth;
            const char *indent;
            const char *containerPadding;
            const char *keyPaddingLeft;
            const char *keyPaddingRight;
            ContainerLayout defaultContainerLayout;
            bool forceDefaultContainerLayout;
    
            struct Container
            {
                ContainerType type;
                ContainerLayout layout;
                bool isKey;
                int childCount;
    
                Container (ContainerType type , ContainerLayout layout):
                    type (type),
                    layout(layout),
                    isKey(false),
                    childCount(0)
                    {
    
                    }
            };
    
            std::stack<Container *> depth;
            void Indent();
    };
    
    #endif

    .cpp文件

    /*
    json-writer.cpp
    */
    #include"json-writer.h"
    
    using namespace std;
    
    void JsonWriter::Indent()
    {
        for (int i = 0, s = initialIndentDepth + depth.size(); i < s; i++)
        {
            Write() << indent;
        }
    }
    
    void JsonWriter::StartChild(bool isKey)
    {
        if (0 == depth.size())
        {
            if (initialIndentDepth > 0)
            {
                Indent();
            }
            return;
        }
    
        Container *container = depth.top();
        if (container->childCount > 0 &&
            (container->type == CONTAINER_TYPE_ARRAY ||
            (container->type == CONTAINER_TYPE_OBJECT && !container->isKey)))
        {
            Write() << ",";
    
            if (container->layout == CONTAINER_LAYOUT_SINGLE_LINE)
            {
                Write() << containerPadding;
            }
            else
            {
                Write() << endl;
                Indent();
            }        
        }
        else if (container->childCount == 0)
        {
            Write() << containerPadding;
            if (container->layout == CONTAINER_LAYOUT_MULTI_LINE)
            {
                Write() << endl;
                Indent();
            }
        }
        
        container->isKey = isKey;
        container->childCount++;
    }
    
    void JsonWriter::Key (const char *key)
    {
        StartChild (true);
        WriteString(key);
        Write() << keyPaddingLeft << ":" << keyPaddingRight;
    }
    
    void JsonWriter::NullValue()
    {
        StartChild();
        Write() << "null";
    }
    
    void JsonWriter::Value(const char * value)
    {
        StartChild();
        WriteString(value);
    }
    
    void JsonWriter::Value(string value)
    {
        StartChild();
        WriteString(value.c_str());
    }
    
    void JsonWriter::Value (bool value)
    {
        StartChild();
        Write() << (value ? "true" : "false");
    }
    
     
    void JsonWriter::StartContainer(ContainerType type, ContainerLayout layout)
    {
        if (forceDefaultContainerLayout)
        {
            layout = defaultContainerLayout;
        }
        else if (layout == CONTAINER_LAYOUT_INHERIT)
        {
            if (depth.size() > 0)
            {
                layout = depth.top()->layout;
            }
            else
            {
                layout = defaultContainerLayout;
            }        
        }
    
        StartChild();
        depth.push(new Container(type, layout));
        Write() << (type == CONTAINER_TYPE_OBJECT ? '{' : '[');
    }
    
    void JsonWriter::EndContainer()
    {
        Container *container = depth.top();
        depth.pop();
    
        if (container->childCount > 0)
        {
            if (container->layout == CONTAINER_LAYOUT_MULTI_LINE)
            {
                Write() << endl;
                Indent();
            }
            else
            {
                Write() << containerPadding;
            }        
        }
    
        Write() << (container->type == CONTAINER_TYPE_OBJECT ? '}' : ']');
    
        delete container;
    }
    
    void JsonWriter::WriteEscapedChar(char c)
    {
        switch(c)
        {
            case '"': Write() << "\""; break;
            case '\': Write() << "\\"; break;
            case '': Write() << "\b"; break;
            case 'f': Write() << "\f"; break;
            case '
    ': Write() << "\n"; break;
            case '
    ': Write() << "\r"; break;
            case '	': Write() << "\t"; break;
            default: Write() << c; break;
        }
    }
    
    void JsonWriter::WriteString(const char *str)
    {
        Write() << """;
        for (int i = 0; str[i] != 0; i++)
        {
            WriteEscapedChar(str[i]);
        }
    
        Write() << """;
    }

    简单测试代码:

    #include<iostream>
    #include<cmath>
    #include"json-writer.h"
    
    int main()
    {
        auto writer = new JsonWriter;
        writer->StartArray();
    
        writer->StartShortObject();
        writer->KeyValue("name", "shiyanlou");
        writer->KeyValue("age", "3");
        writer->EndObjct();
    
        writer->StartObject();
        writer->KeyValue("skills", "c++");
        writer->KeyValue("skills", "python");
        writer->KeyValue("skills", "php");
        writer->KeyValue("skills", "java");
        writer->KeyValue("uri", "http://shiyanlou.com");
    
        writer->Key("path");
        writer->StartArray();
        writer->Value("web");
        writer->Value("algorithm");
        writer->Value("linux");
        writer->EndArray();
    
        writer->Key("short-array");
        writer->StartShortArray();
        writer->Value(1);
        writer->Value((uint64_t)0xabcdef123456);
        writer->Value(M_PI);
        writer->EndContainer();
    
        writer->EndObjct();
        writer->Value(false);
        writer->EndArray();
    
    }

    多种格式测试代码:

    #include "json-writer.h"
    
    #define BEGIN_TEST(name)    
    {   
        JsonWriter *w = new JsonWriter; 
        w->SetInitialIndentDepth(2);    
        if (compress)   
        {   
            w->ConfigureCompressedOutput(); 
        }   
        cout << #name <<  ":" << endl << endl;   
    
    #define END_TEST    
        delete w;   
        cout << endl << endl;    
    }
    
    int main()
    {
        bool compress;
    
        for (int i = 0; i < 2; compress = i == 0, i++)
        {
            BEGIN_TEST(null)
                w->NullValue();
            END_TEST
    
            BEGIN_TEST(bool-false)
                w->Value(false);
            END_TEST
    
            BEGIN_TEST(bool-true)
                w->Value(true);
            END_TEST
    
            BEGIN_TEST(int)
                w->Value(30000);
            END_TEST
    
            BEGIN_TEST(double)
                w->Value(0.131415926);
            END_TEST
    
            BEGIN_TEST(empty-string)
                w->Value("");
            END_TEST
    
            BEGIN_TEST(simple-string)
                w->Value("Hello");
            END_TEST
    
            BEGIN_TEST(escaped-string)
                w->Value(""newline
    tab	"");
            END_TEST
    
            BEGIN_TEST(empty-object)
                w->StartObject();
                w->EndObjct();
            END_TEST
    
            BEGIN_TEST(empty-array)
                w->StartArray();
                w->EndArray();
            END_TEST
    
            BEGIN_TEST(short-object)
                w->StartShortObject();
                w->KeyValue("name", "Aaron");
                w->EndObjct();
            END_TEST
    
            BEGIN_TEST(short-array)
                w->StartShortArray();
                for(int i = 0; i < 10; i++)
                {
                    w->Value(i);
                }
                w->EndArray();
            END_TEST
    
            BEGIN_TEST(array-with-object)
                w->StartArray();
                    w->StartShortObject();
                        w->KeyValue("name", "Aaron");
                        w->KeyValue("age", 7);
                    w->EndObjct();
                    w->StartObject();
                        w->KeyValue("animal", "cat");
                        w->KeyValue("life-expectancy", "forever");
                        w->KeyValue("url", "http://catoverflow.com");
                        w->Key("catch-phrases");
                        w->StartArray();
                            w->Value("meow");
                            w->Value("hiss");
                            w->Value("purr");
                        w->EndArray();
                    w->EndObjct();  
                    w->Value(false);
                w->EndArray();
            END_TEST
    
            BEGIN_TEST(nested-objects)
                w->StartObject();
                    w->Key("a");
                    w->StartObject();
                        w->Key("b");
                        w->StartObject();
                            w->Key("c");
                            w->StartObject();
                            w->EndObjct();
                        w->EndObjct();
                    w->EndObjct();
                w->EndArray();
            END_TEST
    
            BEGIN_TEST(nested-arrays)
                w->StartArray();
                    w->StartArray();
                        w->StartArray();
                            w->StartArray();
                            w->EndArray();
                        w->EndArray();
                    w->EndArray();
                w->EndArray();
            END_TEST
        }
    
        return 0;
    }

    makefile文件:

    CXXFLAGS = -Wall -g -std=c++11
    
    all: test json-writer-test
    clean: 
        rm -rf *.o test json-writer-test
    
    test: json-writer.h json-writer.cpp test.cpp
        $(CXX) $(CXXFLAGS) json-writer.h json-writer.cpp test.cpp -o test
    
    json-writer-test: json-writer-test.cpp json-writer.h json-writer.cpp
        $(CXX) $(CXXFLAGS) json-writer.h json-writer.cpp json-writer-test.cpp -o json-writer-test    

    运行结果就不放了。

    版权归于实验楼

  • 相关阅读:
    Spring学习(一)初识Spring
    搜索引擎学习(七)解析查询
    搜索引擎学习(六)Query的子类查询
    Oracle学习(十四)分表分区
    Oracle学习(十三)优化专题
    Python学习————流程控制之while循环
    Python学习————深浅copy
    Python学习————while循环作业
    Python学习————运算符
    Python学习————与用户交互
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/12238600.html
Copyright © 2011-2022 走看看