欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

简单 JSON 解析和转储的 C++ 实现

最编程 2024-10-19 13:55:40
...

FCJson.h

#pragma once
#include <stdint.h>
#include <string>
#include <vector>
#include <map>

// VS 将执行字符集指定为 UTF-8
// 项目属性页 -> 配置属性 -> C/C++ -> 命令行 -> 其他选项(D) 
// 加入 /execution-charset:utf-8 或/utf-8
//

// 此编译器指令在 Visual Studio 2015 Update 2 及更高版本中已过时
// #pragma execution_character_set("utf-8")

// JSON规范: https://www.json.org/json-zh.html

#ifdef _UNICODE

#define __T(x)      L ## x
using _tstring = std::wstring;
using _tchar = wchar_t;
using _utchar = _tchar;

#else

#define __T(x)      x
using _tstring = std::string;
using _tchar = char;
using _utchar = unsigned char;

#endif

#define _T(x)       __T(x)
#define _TEXT(x)    __T(x)

// JSON 解析
// FlameCyclone
namespace FCJson
{
    class JsonValue;
    using JsonNull = void*;
    using JsonBool = bool;
    using JsonInt = int64_t;
    using JsonFloat = double;
    using JsonString = _tstring;
    using JsonObject = std::map<_tstring, JsonValue>;
    using JsonArray = std::vector<JsonValue>;

    // 异常
    class JsonException
    {
    public:
        JsonException(const _tstring& msg, const _tchar* pStrPos = nullptr) :
            m_Message(msg)
        {
            if (nullptr != pStrPos)
            {
                m_TextPos = pStrPos;
            }
        }

        _tstring GetMessage() const
        {
            return m_Message;
        }

        _tstring GetTextPos() const
        {
            return m_Message;
        }

    private:
        _tstring    m_Message;      // 提示
        _tstring    m_TextPos;      // 异常起始文本
    };

    // JSON 数据类型
    enum JsonType
    {
        eNone,              // 不存在
        eNull,              // 空值
        eString,            // 字符串
        eInteger,           // 整数
        eFloat,             // 浮点数
        eBool,              // 布尔
        eObject,            // 对象
        eArray,             // 数组
    };

    // JSON 编码
    enum JsonEnc
    {
        eAuto,              // 自动
        eUtf8,              // Utf8
        eUtf16,             // Utf16编码
    };

    // JSON 值类
    class JsonValue
    {
    public:

        // 构造
        JsonValue();
        JsonValue(JsonType type);
        JsonValue(const _tchar* val);
        JsonValue(const JsonBool val);
        JsonValue(const int val);
        JsonValue(const JsonInt val);
        JsonValue(const JsonFloat val);
        JsonValue(const JsonString& val);
        JsonValue(const JsonObject& val);
        JsonValue(const JsonArray& val);
        JsonValue(const JsonValue& r);
        JsonValue(JsonValue&& r) noexcept;

        // 运算符重载
        JsonValue& operator [] (const _tstring& name);
        JsonValue& operator [] (const size_t index);
        JsonValue& operator = (JsonType type);
        JsonValue& operator = (const JsonValue& r);
        JsonValue& operator = (JsonBool val);
        JsonValue& operator = (int val);
        JsonValue& operator = (JsonInt val);
        JsonValue& operator = (JsonFloat val);
        JsonValue& operator = (const _tchar* val);
        JsonValue& operator = (const JsonString& val);
        JsonValue& operator = (const JsonObject& val);
        JsonValue& operator = (const JsonArray& val);

        // 清空
        void Clear();

        ~JsonValue();

        // 检查与类型判断
        JsonType GetType() const;
        _tstring GetTypeName() const;

        // 类型判断
        bool IsValid() const;
        bool IsNull() const;
        bool IsBool() const;
        bool IsInt() const;
        bool IsFloat() const;
        bool IsString() const;
        bool IsObject() const;
        bool IsArray() const;

        // 获取数据
        JsonBool AsBool() const;
        JsonInt AsInt() const;
        JsonFloat AsFloat() const;
        JsonString AsString() const;
        JsonObject AsObject() const;
        JsonArray AsArray() const;

        // 
        // @brief: 获取本身或子项计数
        // @param: name             子项(空字符串: 本身对象或数组的计数 非空: 对象子项的计数)
        // @ret: size_t             计数, 非数组或对象时返回1, 不存在返回0
        size_t Count(const _tstring name = _T("")) const;

        // 
        // @brief: 从文本解析(仅支持 UTF8 或 UTF16编码的文本)
        // @param: strText          文本内容
        // @ret: JsonValue          JSON值
        JsonValue Parse(const _tstring strText);

        // 
        // @brief: 从文件解析(仅支持 UTF8 或 UTF16编码的文件)
        // @param: strPath          文件路径
        // @ret: JsonValue          JSON值
        JsonValue ParseFile(const _tstring strPath);

        // 
        // @brief: 转储为文本
        // @param: indent           空白字符数量
        // @param: fEscapeCh        是否转义非Ascii字符
        // @ret: std::wstring       转储文本
        _tstring Dump(int indent = 0, bool fEscapeCh = false) const;

        // 
        // @brief: 转储到文件
        // @param: strPath          文件路径
        // @param: indent           空白字符数量
        // @param: enc              Unicode编码类型(UTF8或UTF16)
        // @param: fEscapeCh        是否转义非Ascii字符
        // @ret: std::wstring       转储文本
        bool DumpFile(const _tstring strPath, int indent = 0, JsonEnc enc = JsonEnc::eAuto, bool fEscapeCh = false);

    private:

        const JsonValue& _GetNone() const;
        JsonValue _ParseFromStringPtr(const _tchar* pData, bool fFromFile);
        JsonValue _ParseFromStringPtr(const _tchar* pData, const _tchar** pEnd, bool fFromFile);
        bool _ParseJsonString(const _tchar* pData, _tstring& val, const _tchar** pEnd, bool fFromFile);
        bool _ParseJsonObject(const _tchar* pData, JsonValue& val, const _tchar** pEnd, bool fFromFile);
        bool _ParseJsonArray(const _tchar* pData, JsonValue& val, const _tchar** pEnd, bool fFromFile);
        bool _ParseJsonValue(const _tchar* pData, JsonValue& val, const _tchar** pEnd, bool fFromFile);
        bool _ParseJsonNumberValue(const _tchar* pData, JsonValue& val, const _tchar** pEnd);
        _tstring _Dump(int depth, int indent, bool fEscapeCh) const;
        _tstring _DumpString(const _tstring strText, bool fEscapeCh) const;
        _tstring _DumpObject(int depth, int indent, bool fEscapeCh) const;
        _tstring _DumpArray(int depth, int indent, bool fEscapeCh) const;

    private:
        JsonArray   m_Array;        // 数组
        JsonObject  m_Object;       // 键值对
        JsonString  m_String;       // 字符串
        JsonFloat   m_Float;        // 浮点数
        JsonInt     m_Integer;      // 整数
        JsonBool    m_Bool;         // 布尔值
        JsonType    m_Type;         // 类型
        _tstring    m_ErrorText;    // 异常起始文本
        static JsonValue m_None;    // 不存在
    };
}

FCJson.cpp

#include "FCJson.h"
#include <cwctype>
#include <fstream>

// UTF-8 编码标准
// 
// 1字节 U+0000000 - U+0000007F 0xxxxxxx
// 2字节 U+0000080 - U+000007FF 110xxxxx 10xxxxxx
// 3字节 U+0000800 - U+0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
// 4字节 U+0010000 - U+001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// 5字节 U+0200000 - U+03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// 6字节 U+4000000 - U+7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

// UTF16 编码标准
// 
// 基本多语言平面(U+0000 - U+FFFF)
// 
// 辅助平面(U+10000 - U+10FFFF)
// 1.码位减去 0x10000,得到20位的代理值(0x00 - 0xFFFFF)
// 2.高10位(范围0 - 0x3FF)加 0xD800 得到高位代理(0xD800 - 0xDBFF)
// 3.低10位(范围0 - 0x3FF)加 0xDC00 得到低位代理(0xDC00 - 0xDFFF)

namespace FCJson
{
#ifdef _UNICODE

#define _istxdigit          std::iswxdigit
#define _istdigit           std::iswdigit
#define _tcsnicmp           _wcsnicmp
#define _tcsstr             wcsstr
#define _tcstod             std::wcstof
#define _tcstol             std::wcstol
#define _tcstoll            std::wcstoll
#define _stprintf_s         swprintf_s
#define _tostring           std::to_wstring
#else

#define _istxdigit          std::iswxdigit
#define _istdigit           std::iswdigit
#define _tcsnicmp           _strnicmp
#define _tcsstr             strstr
#define _tcstod             std::strtof
#define _tcstol             std::strtol
#define _tcstoll            std::strtoll
#define _stprintf_s         sprintf_s
#define _tostring           std::to_string

#endif

    static std::string _CodePointToUtf8(uint32_t cp32);
    static bool _GetUnicodeCodePoint(const _tchar* pData, uint32_t* pCp, const _tchar** pEnd);
    static int32_t _Utf8ToUtf16(const void* pData, size_t size = -1, std::string* pUtf8 = nullptr, std::wstring* pUtf16 = nullptr);
    static int32_t _Utf16ToUtf8(const void* pData, size_t size = -1, std::string* pUtf8 = nullptr, std::wstring* pUtf16 = nullptr);
    const _tchar* _SkipStringWhitespace(const _tchar* pData);
    const _tchar* _SkipStringBom(const _tchar* pData);
    static bool _SkipDigit(const _tchar* pData, const _tchar** pEnd);

    JsonValue JsonValue::m_None(JsonType::eNone);

    JsonValue::JsonValue()
        :
        m_Bool(false),
        m_Integer(0),
        m_Float(0.0f),
        m_Type(JsonType::eNull)
    {
    }

    JsonValue::JsonValue(JsonType type) : JsonValue()
    {
        m_Type = type;
    }

    JsonValue::JsonValue(const _tchar* val) : JsonValue(_tstring(val))
    {
    }

    JsonValue::JsonValue(const JsonBool val) : JsonValue()
    {
        m_Type = JsonType::eBool;
        m_Bool = val;
    }

    JsonValue::JsonValue(const int val) : JsonValue()
    {
        m_Type = JsonType::eInteger;
        m_Integer = val;
    }

    JsonValue::JsonValue(const JsonInt val) : JsonValue()
    {
        m_Type = JsonType::eInteger;
        m_Integer = val;
    }

    JsonValue::JsonValue(const JsonFloat val) : JsonValue()
    {
        m_Type = JsonType::eFloat;
        m_Float = val;
    }

    JsonValue::JsonValue(const JsonString& val) : JsonValue()
    {
        m_Type = JsonType::eString;
        m_String = val;
    }

    JsonValue::JsonValue(const JsonObject& val) : JsonValue()
    {
        m_Type = JsonType::eObject;
        m_Object = val;
    }

    JsonValue::JsonValue(const JsonArray& val) : JsonValue()
    {
        m_Type = JsonType::eArray;
        m_Array = val;
    }

    JsonValue::JsonValue(const JsonValue& r) : JsonValue()
    {
        m_Type = r.m_Type;
        m_Bool = r.m_Bool;
        m_Integer = r.m_Integer;
        m_Float = r.m_Float;
        m_String = r.m_String;
        m_Object = r.m_Object;
        m_Array = r.m_Array;
    }

    JsonValue::JsonValue(JsonValue&& r) noexcept : JsonValue()
    {
        m_Type = r.m_Type;
        m_Bool = r.m_Bool;
        m_Integer = r.m_Integer;
        m_Float = r.m_Float;
        m_String = std::move(r.m_String);
        m_Object = std::move(r.m_Object);
        m_Array = std::move(r.m_Array);
    }

    JsonValue& JsonValue::operator[](const _tstring& name)
    {
        if (!IsObject())
        {
            throw JsonException(_T("Type Error"), _T("operator[] JsonType::eObject == m_Type"));
        }

        auto itFind = m_Object.find(name);
        if (m_Object.end() == itFind)
        {
            m_Object.insert(std::make_pair(name, JsonValue()));
        }

        itFind = m_Object.find(name);

        return itFind->second;
    }

    JsonValue& JsonValue::operator[](const size_t index)
    {
        if (JsonType::eArray != m_Type)
        {
            throw JsonException(_T("Type Error"), _T("operator[] JsonType::eArray == m_Type"));
        }

        if (m_Array.size() <= index)
        {
            m_Array.resize(index + 1);
        }

        return m_Array[index];
    }

    JsonValue& JsonValue::operator = (JsonType type)
    {
        if (type != m_Type)
        {
            Clear();
            m_Type = type;
        }

        return *this;
    }

    JsonValue& JsonValue::operator = (const JsonValue& r)
    {
        if (&r != this)
        {
            Clear();
            m_Type = r.m_Type;
            if (m_Type == JsonType::eBool) m_Bool = r.m_Bool;
            if (m_Type == JsonType::eInteger) m_Integer = r.m_Integer;
            if (m_Type == JsonType::eFloat) m_Float = r.m_Float;
            if (m_Type == JsonType::eString) m_String = r.m_String;
            if (m_Type == JsonType::eObject) m_Object = r.m_Object;
            if (m_Type == JsonType::eArray) m_Array = r.m_Array;
        }

        return *this;
    }

    JsonValue& JsonValue::operator = (JsonBool val)
    {
        if (JsonType::eBool != m_Type)
        {
            Clear();
            m_Type = JsonType::eBool;
        }

        m_Bool = val;

        return *this;
    }

    JsonValue& JsonValue::operator = (int val)
    {
        if (IsValid())
        {
            return *this;
        }

        if (JsonType::eInteger != m_Type)
        {
            Clear();
            m_Type = JsonType::eInteger;
        }

        m_Integer = val;

        return *this;
    }

    JsonValue& JsonValue::operator = (JsonInt val)
    {
        if (IsValid())
        {
            return *this;
        }

        if (JsonType::eInteger != m_Type)
        {
            Clear();
            m_Type = JsonType::eInteger;
        }

        m_Integer = val;

        return *this;
    }

    JsonValue& JsonValue::operator = (JsonFloat val)
    {
        if (IsValid())
        {
            return *this;
        }

        if (JsonType::eFloat != m_Type)
        {
            Clear();
            m_Type = JsonType::eFloat;
        }

        m_Float = val;

        return *this;
    }

    JsonValue& JsonValue::operator = (const _tchar* val)
    {
        if (IsValid())
        {
            return *this;
        }

        if (JsonType::eString != m_Type)
        {
            Clear();
            m_Type = JsonType::eString;
        }

        m_String = val;

        return *this;
    }

    JsonValue& JsonValue::operator = (const JsonString& val)
    {
        if (IsValid())
        {
            return *this;
        }

        if (JsonType::eString != m_Type)
        {
            Clear();
            m_Type = JsonType::eString;
        }

        m_String = val;

        return *this;
    }

    JsonValue& JsonValue::operator = (const JsonObject& val)
    {
        if (IsValid())
        {
            return *this;
        }

        if (JsonType::eObject != m_Type)
        {
            Clear();
            m_Type = JsonType::eObject;
        }

        m_Object = val;

        return *this;
    }

    JsonValue& JsonValue::operator = (const JsonArray& val)
    {
        if (IsValid())
        {
            return *this;
        }

        if (JsonType::eArray != m_Type)
        {
            Clear();
            m_Type = JsonType::eArray;
        }

        m_Array = val;

        return *this;
    }

    JsonValue::~JsonValue()
    {

    }

    JsonType JsonValue::GetType() const
    {
        return m_Type;
    }

    _tstring JsonValue::GetTypeName() const
    {
        if (JsonType::eNull == m_Type) return _T("Null");
        if (JsonType::eBool == m_Type) return _T("Bool");
        if (JsonType::eInteger == m_Type) return _T("Integer");
        if (JsonType::eFloat == m_Type) return _T("Float");
        if (JsonType::eString == m_Type) return _T("String");
        if (JsonType::eObject == m_Type) return _T("Object");
        if (JsonType::eArray == m_Type) return _T("Array");
        return _T("None");
    }

    bool JsonValue::IsValid() const
    {
        return JsonType::eNone == m_Type;
    }

    bool JsonValue::IsNull() const
    {
        return JsonType::eNull == m_Type;
    }

    bool JsonValue::IsBool() const
    {
        return JsonType::eBool == m_Type;
    }

    bool JsonValue::IsInt() const
    {
        return JsonType::eInteger == m_Type;
    }

    bool JsonValue::IsFloat() const
    {
        return JsonType::eFloat == m_Type;
    }

    bool JsonValue::IsString() const
    {
        return JsonType::eString == m_Type;
    }

    bool JsonValue::IsObject() const
    {
        return JsonType::eObject == m_Type;
    }

    bool JsonValue::IsArray() const
    {
        return JsonType::eArray == m_Type;
    }

    JsonBool JsonValue::AsBool() const
    {
        if (!JsonType::eBool == m_Type)
        {
            throw JsonException(_T("Type Error"), _T("AsBool(): JsonType::eBool == m_Type"));
        }

        return m_Bool;
    }

    JsonInt JsonValue::AsInt() const
    {
        if (!JsonType::eInteger == m_Type)
        {
            throw JsonException(_T("Type Error"), _T("AsInt(): JsonType::eInteger == m_Type"));
        }

        return m_Integer;
    }

    JsonFloat JsonValue::AsFloat() const
    {
        if (!JsonType::eFloat == m_Type)
        {
            throw JsonException(_T("Type Error"), _T("AsFloat(): JsonType::eFloat == m_Type"));
        }

        return m_Float;
    }

    JsonString JsonValue::AsString() const
    {
        if (!JsonType::eString == m_Type)
        {
            throw JsonException(_T("Type Error"), _T("AsString(): JsonType::eString == m_Type"));
        }

        return m_String;
    }

    JsonObject JsonValue::AsObject() const
    {
        if (!JsonType::eObject == m_Type)
        {
            throw JsonException(_T("Type Error"), _T("AsObject(): JsonType::eObject == m_Type"));
        }

        return m_Object;
    }

    JsonArray JsonValue::AsArray() const
    {
        if (!JsonType::eArray == m_Type)
        {
            throw JsonException(_T("Type Error"), _T("AsArray(): JsonType::eArray == m_Type"));
        }

        return m_Array;
    }

    void JsonValue::Clear()
    {
        m_Bool = false;
        m_Integer = 0;
        m_Float = 0.0f;
        m_String.clear();
        m_Object.clear();
        m_Array.clear();
        m_ErrorText.clear();
        m_Type = JsonType::eNull;
    }

    size_t JsonValue::Count(const _tstring name) const
    {
        if (JsonType::eNone == m_Type)
        {
            return 0;
        }

        if (name.empty())
        {
            if (JsonType::eObject == m_Type)
            {
                return m_Object.size();
            }

            if (JsonType::eArray == m_Type)
            {
                return m_Array.size();
            }

            return 1;
        }

        auto itFind = m_Object.find(name);
        if (m_Object.end() == itFind)
        {
            return 0;
        }

        return itFind->second.Count();
    }

    bool JsonValue::_ParseJsonString(const _tchar* pData, _tstring& val, const _tchar** pEnd, bool fFromFile)
    {
        const _tchar* pStart = pData;
        bool fAbort = false;

        // 跳过空格
        pData = _SkipStringWhitespace(pData);

        // 检查双引号
        if (_T('\"') != *pData)
        {
            return false;
        }

        pData++;
        pStart = pData;

        _tstring strResult;

        while (_T('\0') != *pData)
        {
            _tchar ch = *pData;
            if (_T('\"') == ch)
            {
                break;
            }

            if (fFromFile)
            {
                if (_T('\\') == ch)
                {
                    pData++;
                    ch = *pData;

                    switch (ch)
                    {
                    case _T('\"'):
                    {
                        strResult.push_back(_T('\"'));
                    }
                    break;
                    case _T('\\'):
                    {
                        strResult.push_back(_T('\\'));
                    }
                    break;
                    case _T('/'):
                    {
                        strResult.push_back(_T('/'));
                    }
                    break;
                    case _T('b'):
                    {
                        strResult.push_back(_T('\b'));
                    }
                    break;
                    case _T('n'):
                    {
                        strResult.push_back(_T('\n'));
                    }
                    break;
                    case _T('r'):
                    {
                        strResult.push_back(_T('\r'));
                    }
                    break;
                    case _T('t'):
                    {
                        strResult.push_back(_T('\t'));
                    }
                    break;
                    case _T('u'):
                    {
                        pData++;

                        uint32_t cp32 = 0;
                        if (!_GetUnicodeCodePoint(pData, &cp32, &pData))
                        {
                            fAbort = true;
                            break;
                        }

                        // 高位
                        if (cp32 >= 0xD800 && cp32 <= 0xDBFF)
                        {
                            cp32 -= 0xD800;

                            if (0 != _tcsnicmp(_T(R"(\u)"), pData, 2))
                            {
                                fAbort = true;
                                break;
                            }

                            pData += 2;

                            uint32_t cpLo = 0;
                            if (!_GetUnicodeCodePoint(pData, &cpLo, &pData))
                            {
                                fAbort = true;
                                break;
                            }

                            // 低位
                            if (cpLo >= 0xDC00 && cpLo <= 0xDFFF)
                            {
                                cpLo -= 0xDC00;

                                cp32 = 0x10000 + ((cp32 << 10) | cpLo);
#ifdef _UNICODE
                                uint16_t cp = (uint16_t)(cp32 - 0x10000);
                                uint16_t cp32Hi = (uint16_t)(cp >> 10) + 0xD800;
                                uint16_t cp32Lo = (uint16_t)(cp & 0x3FF) + 0xDC00;
                                strResult.push_back(cp32Hi);
                                strResult.push_back(cp32Lo);
#else
                                strResult += _CodePointToUtf8(cp32);
#endif
                            }
                            else
                            {
                                fAbort = true;
                                break;
                            }
                        }
                        else
                        {
#ifdef _UNICODE
                            strResult.push_back((_tchar)cp32);
#else
                            strResult += _CodePointToUtf8(cp32);
#endif
                        }

                        continue;
                    }
                    break;
                    default:
                        pData--;
                        fAbort = true;
                        break;
                    }
                }
                else
                {
                    strResult.push_back(ch);
                }
            }
            else
            {
                strResult.push_back(ch);
            }

            if (fAbort)
            {
                break;
            }
            pData++;
        }

        // 检查双引号
        if (_T('\"') != *pData || fAbort)
        {
            *pEnd = pData;
            return false;
        }

        pData++;

        val = strResult;

        if (pEnd)
        {
            *pEnd = pData;
        }

        return true;
    }

    _tstring FloatToString(double fNumber)
    {
        _tstring strResult;
        strResult = _tostring(fNumber);
        size_t posDot = strResult.find(_T('.'));
        if (_tstring::npos == posDot)
        {
            strResult += _T(".0");
        }
        else
        {
            size_t nSize = strResult.size();
            for (auto it = strResult.rbegin(); strResult.rend() != it; it++)
            {
                if (_T('0') == *it)
                {
                    nSize--;
                }
                else if (_T('.') == *it)
                {
                    strResult.resize(nSize);
                    strResult += _T("0");
                    break;
                }
                else
                {
                    strResult.resize(nSize);
                    break;
                }
            }
        }

        return strResult;
    }

    _tstring JsonValue::_DumpString(const _tstring strText, bool fEscapeCh) const
    {
        const _tchar* pData = strText.c_str();
        _tstring strResult;
        strResult.reserve(strText.size());

        while (_T('\0') != *pData)
        {
            _utchar ch = *pData;

            if (_T('\"') == ch)
            {
                strResult += _T(R"(\")");
            }
            else if (_T('\\') == ch)
            {
                strResult += _T(R"(\\)");
            }
            else if (_T('/') == ch)
            {
                strResult += _T(R"(/)");
            }
            else if (_T('\b') == ch)
            {
                strResult += _T(R"(\b)");
            }
            else if (_T('\f') == ch)
            {
                strResult += _T(R"(\f)");
            }
            else if (_T('\n') == ch)
            {
                strResult += _T(R"(\n)");
            }
            else if (_T('\r') == ch)
            {
                strResult += _T(R"(\r)");
            }
            else if (_T('\t') == ch)
            {
                strResult += _T(R"(\t)");
            }
            else
            {
#ifdef _UNICODE
                _tchar szBuf[32] = { 0 };
                if (ch < 0x80 || !fEscapeCh)
                {
                    strResult.push_back(ch);
                    pData++;
                    continue;
                }

                _stprintf_s(szBuf, sizeof(szBuf) / sizeof(_tchar), _T(R"(\u%0.4x)"), ch);
                strResult += szBuf;

#else
                bool fResult = true;
                if (ch < 0x80 || !fEscapeCh)
                {
                    strResult.push_back(ch);
                    pData++;
                    continue;
                }

                if (ch >= 0xC0)
                {
                    uint8_t u8CodeMask = 0xC0;     // 11000000
                    uint8_t u8DataMask = 0x1F;      // 000xxxxx
                    int nCount = 2;                 // 有效字节数量: 2-6

                    // 检索字符使用的字节数量
                    size_t nByteCount = 0;
                    uint32_t cp32 = 0;
                    while (u8CodeMask <= 0xFC)
                    {
                        uint8_t u8MaskMax = u8CodeMask | u8DataMask;
                        if (ch >= u8CodeMask && ch <= u8MaskMax)
                        {
                            cp32 = ch & u8DataMask;
                            nByteCount = nCount;
                            break;
                        }

                        u8CodeMask = (u8CodeMask >> 1) | 0x80;
                        u8DataMask = u8DataMask >> 1;
                        nCount++;
                    }

                    if (0 == nByteCount)
                    {
                        fResult = false;
                        break;
                    }

                    for (size_t i = 1; i < nByteCount; i++)
                    {
                        cp32 = cp32 << 6;
                        cp32 |= pData[i] & 0x3F;
                    }

                    char szBuf[32] = { 0 };
                    if (cp32 < 0x10000)
                    {
                        sprintf_s(szBuf, sizeof(szBuf), R"(\u%0.4x)", cp32);
                        strResult += szBuf;
                    }
                    else
                    {
                        uint32_t cp = (uint16_t)(cp32 - 0x10000);
                        uint16_t cp32Hi = (uint16_t)(cp >> 10) + 0xD800;
                        uint16_t cp32Lo = (uint16_t)(cp & 0x3FF) + 0xDC00;

                        sprintf_s(szBuf, sizeof(szBuf), R"(\u%0.4x)", cp32Hi);
                        strResult += szBuf;

                        sprintf_s(szBuf, sizeof(szBuf), R"(\u%0.4x)", cp32Lo);
                        strResult += szBuf;
                    }

                    pData += nByteCount;
                    continue;
                }
#endif
            }
            pData++;
        }

        return strResult;
    }

    _tstring JsonValue::_DumpObject(int depth, int indent, bool fEscapeCh) const
    {
        if (indent < 0)
        {
            indent = 0;
        }

        _tstring strResult;

        _tstring strKeyValInterval = _T("");
        _tstring strReturn = _T("");

        if (indent > 0)
        {
            strKeyValInterval = _T(" ");
            strReturn = _T("\r\n");
        }

        strResult = _T("{");
        strResult += strReturn;
        depth++;

        size_t size = m_Object.size();
        for (const auto& item : m_Object)
        {
            strResult += _tstring(depth * indent, _T(' '));
            strResult += _T("\"");
            strResult += _DumpString(item.first, fEscapeCh);
            strResult += _T("\":");
            strResult += strKeyValInterval;
            strResult += item.second._Dump(depth, indent, fEscapeCh);
            size--;

            if (0 != size)
            {
                strResult += _T(",");
            }

            strResult += strReturn;
        }

        depth--;
        strResult += _tstring(depth * indent, _T(' '));
        strResult += _T("}");

        return strResult;
    }

    _tstring JsonValue::_DumpArray(int depth, int indent, bool fEscapeCh) const
    {
        if (indent < 0)
        {
            indent = 0;
        }

        _tstring strResult;

        _tstring strKeyValInterval = _T("");
        _tstring strReturn = _T("");

        if (indent > 0)
        {
            strKeyValInterval = _T(" ");
            strReturn = _T("\r\n");
        }

        strResult = _T("[");
        strResult += strReturn;
        depth++;

        size_t size = m_Array.size();
        for (const auto& item : m_Array)
        {
            strResult += _tstring(depth * indent, _T(' '));
            strResult += item._Dump(depth, indent, fEscapeCh);
            size--;
            if (0 != size)
            {
                strResult += _T(",");
            }

            strResult += strReturn;
        }

        depth--;
        strResult += _tstring(depth * indent, _T(' '));
        strResult += _T("]");

        return strResult;
    }

    _tstring JsonValue::_Dump(int depth, int indent, bool fEscapeCh) const
    {
        if (indent < 0)
        {
            indent = 0;
        }

        _tstring strResult;
        _tstring strKeyValInterval = _T("");
        _tstring strReturn = _T("");

        if (IsArray() && m_Array.empty())
        {
            return _T("[]");
        }

        if (IsObject() && m_Object.empty())
        {
            return _T("{}");
        }

        if (indent > 0)
        {
            strKeyValInterval = _T(" ");
            strReturn = _T("\r\n");
        }

        if (IsNull())
        {
            strResult = _T("null");
        }
        else if (IsBool())
        {
            strResult = m_Bool ? _T("true") : _T("false");
        }
        else if (IsInt())
        {
            strResult = _tostring(m_Integer);
        }
        else if (IsFloat())
        {
            strResult = FloatToString(m_Float);
        }
        else if (IsString())
        {
            strResult += _T("\"");
            strResult += _DumpString(m_String, fEscapeCh);
            strResult += _T("\"");
        }
        else if (IsObject())
        {
            strResult += _DumpObject(depth, indent, fEscapeCh);
        }
        else if (IsArray())
        {
            strResult += _DumpArray(depth, indent, fEscapeCh);
        }

        return strResult;
    }

    _tstring JsonValue::Dump(int indent/* = 0*/, bool fEscapeCh/* = false*/) const
    {
        return _Dump(0, indent, fEscapeCh);
    }

    bool JsonValue::DumpFile(const _tstring strPath, int indent/* = 0*/, JsonEnc encoding/* = JsonEncoding::eAuto*/, bool fEscapeCh/* = false*/)
    {
        _tstring strResult;
        _tstring strText = _Dump(0, indent, fEscapeCh);

        std::string strUnicode8;
        std::wstring strUnicode16;

        strUnicode8.push_back((uint8_t)0xEF);
        strUnicode8.push_back((uint8_t)0xBB);
        strUnicode8.push_back((uint8_t)0xBF);

        strUnicode16.push_back((uint16_t)0xFEFF);

        std::ofstream outputFile(strPath, std::ios::binary | std::ios::out);
        if (!outputFile.is_open())
        {
            return false;
        }

#ifdef _UNICODE
        strResult = strUnicode16;

        if (JsonEncoding::eUtf16 == encoding || JsonEncoding::eAuto == encoding)
        {
            strResult += strText;
            outputFile.write((const char*)strResult.data(), strResult.size() * sizeof(_tchar));
            outputFile.close();
        }

        if (JsonEncoding::eUtf8 == encoding)
        {
            int32_t nU8Length = _Utf16ToUtf8(strText.c_str(), (size_t)-1, &strUnicode8, nullptr);
            if (nU8Length >= 0)
            {
                outputFile.write((const char*)strUnicode8.data(), strUnicode8.size() * sizeof(char));
                outputFile.close();
            }
        }

#else
        strResult = strUnicode8;

        if (JsonEnc::eUtf8 == encoding || JsonEnc::eAuto == encoding)
        {
            strResult += strText;
            outputFile.write((const char*)strResult.data(), strResult.size() * sizeof(_tchar));
            outputFile.close();
        }

        if (JsonEnc::eUtf16 == encoding)
        {
            int32_t nU8Length = _Utf8ToUtf16(strText.c_str(), (size_t)-1, nullptr, &strUnicode16);
            if (nU8Length >= 0)
            {
                outputFile.write((const char*)strUnicode16.data(), strUnicode16.size() * sizeof(wchar_t));
                outputFile.close();
            }
        }

#endif

        return true;
    }

    JsonValue JsonValue::Parse(const _tstring strText)
    {
        return _ParseFromStringPtr(strText.c_str(), false);
    }

    JsonValue JsonValue::ParseFile(const _tstring strPath)
    {
        std::string strUnicode8;
        std::wstring strUnicode16;
        _tstring strText;

        do
        {
            std::ifstream inputFile(strPath, std::ios::binary | std::ios::in);
            if (!inputFile.is_open())
            {
                *this = JsonType::eNone;
                return *this;
            }

            inputFile.seekg(0, std::ios::end);
            std::streamoff nSize = inputFile.tellg();
            inputFile.seekg(0, std::ios::beg);

            std::string strBuffer(nSize, 0);
            inputFile.read((char*)&strBuffer[0], nSize);
            size_t nByteSize = (size_t)inputFile.gcount();
            inputFile.close();

            if (0 == nByteSize)
            {
                break;
            }

            int32_t nU8Length = _Utf8ToUtf16(strBuffer.data(), strBuffer.size(), &strUnicode8, &strUnicode16);

#ifdef _UNICODE
            if (nU8Length > 0)
            {
                strText = strUnicode16;
                break;
            }
#else
            if (nU8Length > 0)
            {
                strText = strUnicode8;
                break;
            }
#endif

            int32_t nU16Length = _Utf16ToUtf8(strBuffer.data(), strBuffer.size(), &strUnicode8, &strUnicode16);

#ifdef _UNICODE
            if (nU16Length > 0)
            {
                strText = strUnicode16;
                break;
            }
#else
            if (nU16Length > 0)
            {
                strText = strUnicode8;
                break;
            }
#endif

        } while (false);

        return _ParseFromStringPtr(strText.c_str(), true);
    }

    const JsonValue& JsonValue::_GetNone() const
    {
        return m_None;
    }

    JsonValue JsonValue::_ParseFromStringPtr(const _tchar* pData, bool fFromFile)
    {
        Clear();
        const _tchar* pEnd = nullptr;
        *this = _ParseFromStringPtr(pData, &pEnd, fFromFile);

        return *this;
    }

    bool _SkipDigit(const _tchar* pData, const _tchar** pEnd)
    {
        if (0 == _istdigit(*pData))
        {
            return false;
        }

        while (_istdigit(*pData))
        {
            pData++;
        }

        *pEnd = pData;

        return true;
    }

    bool JsonValue::_ParseJsonNumberValue(const _tchar* pData, JsonValue& val, const _tchar** pEnd)
    {
        // [-]?[0-9]+\.[0-9]+[eE]?[-+]?[0-9]+

        const _tchar* pStart = pData;
        bool fDot = false;
        bool fExponent = false;
        bool fResult = false;

        do
        {
            // 符号
            if (_T('-') == *pData)
            {
                pData++;
            }

            // 数字部分
            if (!_SkipDigit(pData, &pData))
            {
                fResult = false;
                break;
            }

            //小数点
            if (_T('.') == *pData)
            {
                fDot = true;
                pData++;
            }

            // 小数部分
            if (fDot)
            {
                if (!_SkipDigit(pData, &pData))
                {
                    break;
                }
            }

            // 指数部分
            if (_T('E') == *pData || _T('e') == *pData)
            {
                fExponent = true;
                pData++;

                // 指数符号
                if (_T('-') == *pData || _T('+') == *pData)
                {
                    pData++;
                }

                if (!_SkipDigit(pData, &pData))
                {
                    break;
                }
            }

            _tstring strNumber(pStart, pData - pStart);
            double fNumber = 0.0f;

            fNumber = _tcstod(strNumber.c_str(), nullptr);

            if (fDot)
            {
                val = fNumber;
            }
            else
            {
                val = (JsonInt)fNumber;
            }

            fResult = true;

        } while (false);

        if (pEnd)
        {
            *pEnd = pData;
        }

        return fResult;
    }

    bool JsonValue::_ParseJsonObject(const _tchar* pData, JsonValue& val, const _tchar** pEnd, bool fFromFile)
    {
        JsonValue valResult(JsonType::eObject);
        bool fResult = false;

        if (_T('{') == *pData)
        {
            pData++;
        }

        while (_T('\0') != *pData)
        {
            _tstring strName;
            JsonValue jsonValue;

            pData = _SkipStringWhitespace(pData);
            if (_T('}') == *pData)
            {
                fResult = true;
                pData++;
                break;
            }

            if (!_ParseJsonString(pData, strName, &pData, fFromFile))
            {
                break;
            }

            pData = _SkipStringWhitespace(pData);
            if (_T(':') != *pData)
            {
                break;
            }
            pData++;

            if (!_ParseJsonValue(pData, jsonValue, &pData, fFromFile))
            {
                break;
            }

            valResult[strName] = jsonValue;

            pData = _SkipStringWhitespace(pData);
            if (_T(',') == *pData)
            {
                pData++;
            }
            else if (_T('}') == *pData)
            {
                fResult = true;
                pData++;
                break;
            }
            else
            {
                break;
            }
        }

        if (fResult)
        {
            val = valResult;
        }

        if (pEnd)
        {
            *pEnd = pData;
        }

        return true;
    }

    bool JsonValue::_ParseJsonArray(const _tchar* pData, JsonValue& val, const _tchar** pEnd, bool fFromFile)
    {
        JsonValue valResult(JsonType::eArray);
        bool fResult = false;

        if (_T('[') == *pData)
        {
            pData++;
        }

        size_t nIndex = 0;
        while (_T('\0') != *pData)
        {
            JsonValue jsonValue;
            pData = _SkipStringWhitespace(pData);
            if (_T(']') == *pData)
            {
                fResult = true;
                pData++;
                break;
            }

            if (!_ParseJsonValue(pData, jsonValue, &pData, fFromFile))
            {
                break;
            }

            if (valResult.m_Array.size() <= nIndex)
            {
                valResult.m_Array.resize(nIndex + 1);
            }

            valResult.m_Array[nIndex] = jsonValue;

            pData = _SkipStringWhitespace(pData);
            if (_T(',') == *pData)
            {
                pData++;
            }
            else if (_T(']') == *pData)
            {
                fResult = true;
                pData++;
                break;
            }
            else
            {
                break;
            }

            nIndex++;
        }

        if (fResult)
        {
            val = valResult;
        }

        if (pEnd)
        {
            *pEnd = pData;
        }

        return fResult;
    }

    bool JsonValue::_ParseJsonValue(const _tchar* pData, JsonValue& val, const _tchar** pEnd, bool fFromFile)
    {
        pData = _SkipStringWhitespace(pData);
        bool fResult = false;

        do
        {
            if (_T('{') == *pData)
            {
                if (!_ParseJsonObject(pData, val, &pData, fFromFile))
                {
                    break;
                }
            }
            else if (_T('[') == *pData)
            {
                if (!_ParseJsonArray(pData, val, &pData, fFromFile))
                {
                    break;
                }
            }
            else
            {
                pData = _SkipStringWhitespace(pData);

                if (0 == _tcsnicmp(_T("null"), pData, 4))
                {
                    val = JsonValue(JsonType::eNull);
                    pData += 4;
                }
                else if(0 == _tcsnicmp(_T("true"), pData, 4))
                {
                    val = true;
                    pData += 4;
                }
                else if(0 == _tcsnicmp(_T("false"), pData, 5))
                {
                    val = false;
                    pData += 5;
                }
                else if (_T('-') == *pData || _istdigit(*pData))
                {
                    if (!_ParseJsonNumberValue(pData, val, &pData))
                    {
                        break;
                    }
                }
                else if (_T('\"') == *pData)
                {
                    _tstring strValue;
                    if (!_ParseJsonString(pData, strValue, &pData, fFromFile))
                    {
                        break;
                    }

                    val = strValue;
                }
                else
                {
                    break;
                }
            }

            fResult = true;

        } while (false);

        if (*pEnd)
        {
            *pEnd = pData;
        }

        return fResult;
    }

    JsonValue JsonValue::_ParseFromStringPtr(const _tchar* pData, const _tchar** pEnd, bool fFromFile)
    {
        JsonValue valResult(JsonType::eNone);

        pData = _SkipStringBom(pData);
        pData = _SkipStringWhitespace(pData);

        while (_T('\0') != *pData)
        {
            if (_T('{') == *pData || _T('[') == *pData)
            {
                if (!_ParseJsonValue(pData, valResult, &pData, fFromFile))
                {
                    m_ErrorText = pData;
                    break;
                }
            }
            else
            {
                m_ErrorText = pData;
                break;
            }

            pData = _SkipStringWhitespace(pData);

            if (_T('\0') != *pData)
            {
                valResult = JsonValue(JsonType::eNone);
                m_ErrorText = pData;
                break;
            }
        }

        if (pEnd)
        {
            *pEnd = pData;
        }

        return valResult;
    }

    const _tchar* _SkipStringWhitespace(const _tchar* pData)
    {
        while (_T('\0') != *pData)
        {
            if (_T(' ' == *pData) ||
                _T('\t' == *pData) ||
                _T('\r' == *pData) ||
                _T('\n' == *pData) ||
                _T('\f' == *pData)
                )
            {
                pData++;
            }
            else
            {
                break;
            }
        }

        return pData;
    }

    const _tchar* _SkipStringBom(const _tchar* pData)
    {
#ifdef _UNICODE

        while (0xFEFF == *pData)
        {
            pData++;
        }

#else
        while (nullptr != _tcsstr(pData, "\xEF\xBB\xBF"))
        {
            pData += 3;
        }

#endif
        return pData;
    }

    bool _GetUnicodeCodePoint(const _tchar* pData, uint32_t* pCp, const _tchar** pEnd)
    {
        _tchar szBuf[16] = { 0 };
        _tchar* pChEnd = nullptr;
        bool fResult = false;

        do
        {
            int count = 0;
            for (count = 0; count < 4; count++)
            {
                _tchar ch = pData[count];
                if (0 == _istxdigit(ch))
                {
                    break;
                }
                szBuf[count] = ch;
            }

            if (4 != count)
            {
                break;
            }

            if (pCp)
            {
                *pCp = _tcstol(szBuf, &pChEnd, 16);
            }

            fResult = true;

        } while (false);

        if (pEnd)
        {
            *pEnd = pData;
        }

        return fResult;
    }

    std::string _CodePointToUtf8(uint32_t cp32)
    {
        char szBuf[16] = { 0 };

        // 1字节 0xxxxxxx
        if (cp32 >= 0x00000000 && cp32 <= 0x0000007F)
        {
            szBuf[0] = (uint8_t)cp32;
            szBuf[1] = 0;
        }

        // 2字节 110xxxxx 10xxxxxx
        if (cp32 >= 0x00000080 && cp32 <= 0x000007FF)
        {
            szBuf[0] = ((cp32 >>  6) & 0x1F) | 0xC0;
            szBuf[1] = ((cp32 & 0x3F)) | 0x80;
            szBuf[2] = 0;
        }

        // 3字节 1110xxxx 10xxxxxx 10xxxxxx
        if (cp32 >= 0x00000800 && cp32 <= 0x0000FFFF)
        {
            szBuf[0] = ((cp32 >> 12) & 0x0F) | 0xE0;
            szBuf[1] = ((cp32 >>  6) & 0x3F) | 0x80;
            szBuf[2] = ((cp32 & 0x3F)) | 0x80;
            szBuf[3] = 0;
        }

        // 4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
        if (cp32 >= 0x00010000 && cp32 <= 0x001FFFFF)
        {
            szBuf[0] = ((cp32 >> 18) & 0x07) | 0xF0;
            szBuf[1] = ((cp32 >> 12) & 0x3F) | 0x80;
            szBuf[2] = ((cp32 >>  6) & 0x3F) | 0x80;
            szBuf[3] = ((cp32 & 0x3F)) | 0x80;
            szBuf[4] = 0;
        }

        // 5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        if (cp32 >= 0x00200000 && cp32 <= 0x03FFFFFF)
        {
            szBuf[0] = ((cp32 >> 24) & 0x03) | 0xF8;
            szBuf[1] = ((cp32 >> 18) & 0x3F) | 0x80;
            szBuf[2] = ((cp32 >> 12) & 0x3F) | 0x80;
            szBuf[3] = ((cp32 >>  6) & 0x3F) | 0x80;
            szBuf[4] = ((cp32 & 0x3F)) | 0x80;
            szBuf[5] = 0;
        }

        // 6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        if (cp32 >= 0x04000000 && cp32 <= 0x7FFFFFFF)
        {
            szBuf[0] = ((cp32 >> 30) & 0x01) | 0xFC;
            szBuf[1] = ((cp32 >> 24) & 0x3F) | 0x80;
            szBuf[2] = ((cp32 >> 18) & 0x3F) | 0x80;
            szBuf[3] = ((cp32 >> 12) & 0x3F) | 0x80;
            szBuf[4] = ((cp32 >>  6) & 0x3F) | 0x80;
            szBuf[5] = ((cp32 & 0x3F)) | 0x80;
            szBuf[6] = 0;
        }

        return szBuf;
    }

    int32_t _Utf8ToUtf16(const void* pData, size_t size/* = -1*/, std::string* pUtf8/* = nullptr*/, std::wstring* pUtf16/* = nullptr*/)
    {
        const uint8_t* pCpData = (const uint8_t*)pData;
        std::wstring strOut16;      // 输出UTF16
        std::string strOut8;        // 输出UTF8
        uint32_t cp32 = 0;          // UNICODE码点
        int32_t nByteCount = 0;     // 字节计数
        int32_t nChCount = 0;       // 字符计数
        bool fResult = true;        // 操作结果
        bool fBom = true;           // BOM(Byte Order Mark)

        if (pUtf8)
        {
            strOut8 += *pUtf8;
        }

        if (pUtf16)
        {
            strOut16 += *pUtf16;
        }

        while ((0 != *pCpData) && (0 != size))
        {
            uint8_t ch = *pCpData;

            // 普通 Ascii 也是 UTF-8 一部分
            if (ch < 0x7F)
            {
                cp32 = ch;
                nChCount++;
            }
            else
            {
                // 检查 UTF-8 首字节
                if (0 == nByteCount)
                {
                    cp32 = 0;
                    if (ch >= 0xC0)
                    {
                        uint8_t u8CodeMask  = 0xC0;     // 11000000
                        uint8_t u8DataMask = 0x1F;      // 000xxxxx
                        int nCount = 2;                 // 有效字节数量: 2-6

                        // 检索字符使用的字节数量
                        while(u8CodeMask <= 0xFC)
                        {
                            uint8_t u8MaskMax = u8CodeMask | u8DataMask;
                            if (ch >= u8CodeMask && ch <= u8MaskMax)
                            {
                                cp32 = ch & u8DataMask;
                                nByteCount = nCount;
                                break;
                            }

                            u8CodeMask = (u8CodeMask >> 1) | 0x80;
                            u8DataMask = u8DataMask >> 1;
                            nCount++;
                        }

                        if (0 == nByteCount)
                        {
                            fResult = false;
                            break;
                        }

                        if (0xEF == ch && 3 == nByteCount)
                        {
                            fBom = true;
                        }

                        nByteCount--;
                    }
                    else
                    {
                        fResult = false;
                        break;
                    }
                }
                else
                {
                    // 非首字节掩码: 10xxxxxx
                    if (0x80 != (ch & 0xC0))
                    {
                        fResult = false;
                        break;
                    }

                    // BOM处理
                    if (fBom)
                    {
                        if (0xBB != ch && 2 == nByteCount)
                        {
                            fBom = false;
                        }

                        if (0xBF != ch && 1 == nByteCount)
                        {
                            fBom = false;
                        }
                    }

                    cp32 = cp32 << 6;
                    cp32 |= ch & 0x3F;

                    nByteCount--;

                    if (0 == nByteCount)
                    {
                        // 跳过BOM
                        if (fBom)
                        {
                            fBom = false;
                            pCpData++;
                            continue;
                        }

                        nChCount++;
                    }
                }
            }

            if (0 == nByteCount)
            {
                if (pUtf8)
                {
                    strOut8 += _CodePointToUtf8(cp32);
                }

                if (pUtf16)
                {
                    if (cp32 < 0x10000)
                    {
                        strOut16.push_back((uint16_t)(cp32 & 0xFFFF));
                    }
                    else
                    {
                        uint16_t cp = (uint16_t)(cp32 - 0x10000);
                        uint16_t cp32Hi = (uint16_t)(cp >> 10) + 0xD800;
                        uint16_t cp32Lo = (uint16_t)(cp & 0x3FF) + 0xDC00;

                        strOut16.push_back(cp32Hi);
                        strOut16.push_back(cp32Lo);
                    }
                }
            }

            pCpData++;

            if (-1 != size)
            {
                size--;
            }
        }

        if (!fResult)
        {
            return -1;
        }

        if (pUtf8)
        {
            *pUtf8 = std::move(strOut8);
        }

        if (pUtf16)
        {
            *pUtf16 = std::move(strOut16);
        }

        return nChCount;
    }

    int32_t _Utf16ToUtf8(const void* pData, size_t size/* = -1*/, std::string* pUtf8/* = nullptr*/, std::wstring* pUtf16/* = nullptr*/)
    {
        const uint16_t* pCpData = (const uint16_t*)pData;
        std::wstring strOut16;          // 输出UTF16
        std::string strOut8;            // 输出UTF8
        uint32_t cp32 = 0;              // 32位码点
        uint16_t cp32Hi = 0;            // 32位码点高10位
        uint16_t cp32Lo = 0;            // 32位码点低10位
        uint16_t cp16 = 0;              // 16位码点
        int32_t nByteCount = 0;         // 字节计数
        int32_t nChCount = 0;           // 字符计数
        bool fBigEndian = false;        // 是否大端字节序
        bool fLittleEndian = false;     // 是否小端字节序
        bool fResult = true;            // 操作结果

        if (pUtf8)
        {
            strOut8 += *pUtf8;
        }

        if (pUtf16)
        {
            strOut16 += *pUtf16;
        }

        if (-1 != size)
        {
            if ((size < 2) || (0 != (size % 2)))
            {
                return -1;
            }
        }

        while ((0 != *pCpData) && (0 != size))
        {
            cp16 = *pCpData;

            // BOM检查
            if (0xFFFE == cp16 || 0xFEFF == cp16)
            {
                if (0 == nByteCount)
                {
                    if (0xFFFE == cp16) // 大端字节序 (Big Endian)
                    {
                        fBigEndian = true;
                    }

                    if (0xFEFF == cp16) // 小端字节序 (Little Endian)
                    {
                        fLittleEndian = true;
                    }
                }
                else
                {
                    fResult = false;
                    break;
                }

                // 不可能同时存在两种字节序
                if (fBigEndian && fLittleEndian)
                {
                    fResult = false;
                    break;
                }

                pCpData++;

                if (-1 != size)
                {
                    size -= 2;
                }

                continue;
            }

            if (fBigEndian)
            {
                cp16 = ((cp16 >> 8) | (cp16 << 8));
            }

            //检查是否为基本多语言平面(U+0000 - U+FFFF)
            if (!(cp16 >= 0xD800 && cp16 <= 0xDFFF))
            {
                if (cp32Hi > 0) // 高位码点后必须跟着低位码点
                {
                    fResult = false;
                    break;
                }

                cp32 = cp16;
                nChCount++;
            }
            else
            {
                if (0 == nByteCount)
                {
                    //检查是否为辅助平面(U+10000 - U+10FFFF)
                    if (cp16 >= 0xD800 && cp16 <= 0xDBFF)   //检查高位代理(0xD800 - 0xDBFF)
                    {
                        cp32Hi = (cp16 - 0xD800);
                        nByteCount = 1;
                    }
                    else
                    {
                        fResult = false;
                        break;
                    }
                }
                else
                {
                    if (1 == nByteCount) // 高位码点后必须接着低位码点
                    {
                        if (cp16 >= 0xDC00 && cp16 <= 0xDFFF)   //检查低位代理(0xDC00 - 0xDFFF)
                        {
                            cp32Lo = (cp16 - 0xDC00);
                            cp32 = 0x10000 + ((uint32_t)cp32Hi << 10 | cp32Lo);
                            cp32Lo = 0;
                            cp32Hi = 0;
                        }
                        else
                        {
                            fResult = false;
                            break;
                        }
                    }

                    nByteCount--;

                    if (0 == nByteCount)
                    {
                        nChCount++;
                    }
                }
            }

            // 转换为 UTF 编码
            if (0 == nByteCount)
            {
                if (pUtf8)
                {
                    strOut8 += _CodePointToUtf8(cp32);
                }

                if (pUtf16)
                {
                    if (cp32 < 0x10000)
                    {
                        strOut16.push_back((uint16_t)(cp32 & 0xFFFF));
                    }
                    else
                    {
                        uint16_t cp = (uint16_t)(cp32 - 0x10000);
                        uint16_t cpHi = (uint16_t)(cp >> 10) + 0xD800;
                        uint16_t cpLo = (uint16_t)(cp & 0x3FF) + 0xDC00;

                        strOut16.push_back(cpHi);
                        strOut16.push_back(cpLo);
                    }
                }
            }

            pCpData++;

            if (-1 != size)
            {
                size -= 2;
            }
        }

        if (!fResult)
        {
            return -1;
        }

        if (pUtf8)
        {
            *pUtf8 = std::move(strOut8);
        }

        if (pUtf16)
        {
            *pUtf16 = std::move(strOut16);
        }

        return nChCount;
    }
}

main.cpp

#include <iostream>
#include <tchar.h>
#include <locale>
#include <string>
#include "FCJson.h"

int main()
{
    setlocale(LC_ALL, "");

    std::string strUtf8 = "我是地球????";
    std::wstring strUtf16 = L"我是地球????";
    size_t nCount = 0;

    FCJson::JsonValue jsonValue(FCJson::JsonType::eObject);

    jsonValue.ParseFile(_T("text_in.json"));
    jsonValue.DumpFile(_T("text_out.json"), 4, FCJson::eAuto, false);

    jsonValue.ParseFile(_T("data.json"));
    jsonValue.DumpFile(_T("data_out.json"), 4, FCJson::eAuto, false);

    jsonValue[_T("name")] = _T("FlameCyclone");
    jsonValue[_T("age")] = 30;

    jsonValue.DumpFile(_T("info.json"), 4, FCJson::eAuto, false);

    jsonValue.ParseFile(_T("info.json"));

    jsonValue.DumpFile(_T("out.json"), 4, FCJson::eAuto, false);


    return 0;
}

推荐阅读