Json串拼装和分析

从Json官方Demo中捡到一个好用的函数 printValueTree, 可以分析复杂的Json串.

如果遇到不好分析的Json串, 用printValueTree跟一次, 就可以写自己的Json串分析函数.

 写了一个Demo, 工程下载点: srcJsonOpt_2014_0923.rar

工程预览:

 

// srcJsonOpt.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <atlbase.h>
#include <atlconv.h>
#include <tchar.h>
#include <string>
#include <time.h>
#include <algorithm>

#define MAX_JSON_REC_CNT 10 ///< 模拟的Json数据条数最大数量

#include "../jsonCpp/json.h"
#pragma comment(lib, "../lib/jsonCppLib.lib")

const char* cKeyArray[] = {"id", "name", "age", "sex"};
typedef struct _tag_json_desc
{
    std::wstring    str_id;
    std::wstring    str_name;
    std::wstring    str_age;
    std::wstring    str_sex;

    _tag_json_desc()
    {
        str_id = L"";
        str_name = L"";
        str_age = L"";
        str_sex = L"";
    }
}TAG_JSON_DESC;

void make_json_array(std::string& strJsonArray);
void parse_json_array(const std::string& strJsonArray);
void showTAG_JSON_DESC(const TAG_JSON_DESC& jsonDesc);

/// 根据自己要处理的Json串,自定义的处理函数
void parse_my_json_step_1(Json::Value& JsonVal, std::deque<TAG_JSON_DESC>& deqJsonDesc);
void parse_my_json_step_2(Json::Value& JsonVal, std::deque<TAG_JSON_DESC>& deqJsonDesc);
void parse_my_json_step_3(Json::Value& JsonVal, TAG_JSON_DESC& JsonDesc, int iIndex);

void printValueTree(Json::Value &value, const std::wstring& path = L".");
static std::string normalizeFloatingPointStr( double value );

std::string StringFormatVA(char * szFormat, ...);
std::wstring StringFormatV(WCHAR * szFormat, ...);
BOOL GetJsonString(Json::Value& JsonValue, char* pKey, std::wstring& strValue);
BOOL UNICODE_2_UTF8(const WCHAR * pcSrc, std::string & strUtf8);
std::wstring UTF8_2_UNICODE(const std::string& strUTF8);
int enc_unicode_to_utf8_one(
    unsigned long unic, 
    unsigned char *pOutput,
    int outSize);

int _tmain(int argc, _TCHAR* argv[])
{
    USES_CONVERSION;

    std::string     strJsonArray = "";
    std::wstring    strJsonArrayW = L"";
    std::string     strJsonArrayUtf8 = ""; ///< 网页需要utf8

    std::deque<TAG_JSON_DESC>   dqJsonDesc;

    // srand((UINT)time(NULL));

    // make a json string
    // on real project, the json string is from webbrowser or
    // our utf8 json stinrg send to webbrowser
    make_json_array(strJsonArray);
    /**
    */

    strJsonArrayW = A2W(strJsonArray.c_str());
    UNICODE_2_UTF8(strJsonArrayW.c_str(), strJsonArrayUtf8);

    // ok, send strJsonArrayUtf8 to webbrowser

    // we parse json string from webbrowser
    /**
    {
    "id14771":[{"id":"id14771"},{"name":"name11538"},{"age":"age1869"},{"sex":"sex19912"}],
    "id19169":[{"id":"id19169"},{"name":"name15724"},{"age":"age11478"},{"sex":"sex29358"}],
    "id19718":[{"id":"id19718"},{"name":"name19895"},{"age":"age5447"},{"sex":"sex21726"}],
    "id23281":[{"id":"id23281"},{"name":"name16827"},{"age":"age9961"},{"sex":"sex491"}],
    "id25667":[{"id":"id25667"},{"name":"name26299"},{"age":"age17035"},{"sex":"sex9894"}],
    "id26962":[{"id":"id26962"},{"name":"name24464"},{"age":"age5705"},{"sex":"sex28145"}],
    "id292":[{"id":"id292"},{"name":"name12382"},{"age":"age17421"},{"sex":"sex18716"}],
    "id2995":[{"id":"id2995"},{"name":"name11942"},{"age":"age4827"},{"sex":"sex5436"}],
    "id32391":[{"id":"id32391"},{"name":"name14604"},{"age":"age3902"},{"sex":"sex153"}],
    "id41":[{"id":"id41"},{"name":"name18467"},{"age":"age6334"},{"sex":"sex26500"}]
    }
    */

    /// 遍历实现, 原因是没有预期连续的key值
    /// e.g. Json串是服务器传来的Sql查询结果的行记录
    parse_json_array(strJsonArrayUtf8);

    getwchar();
	return 0;
}

void parse_json_array(const std::string& strJsonArray)
{
    /** json串内容 样例, 一行
    "id14771":[{"id":"id14771"},{"name":"name11538"},{"age":"age1869"},{"sex":"sex19912"}],
    */

    USES_CONVERSION;
    bool    bRc = false;
    TAG_JSON_DESC JsonDesc;

    Json::Reader    JsonReader; ///< 解析json用Json::Reader
    Json::Value     JsonRoot;

    std::deque<TAG_JSON_DESC> deqJsonDesc;
    std::deque<TAG_JSON_DESC>::iterator it;

    std::string     str_obj_key = "id41";
    std::string     str_obj_val = "";

    bRc = JsonReader.parse(strJsonArray, JsonRoot, true);
    _ASSERT(true == bRc);

    /// 通过printValueTree(JsonRoot)调试, 决定我们如何分析提取Json数据
    /// 如果提取Json数据的过程不顺利, 可以先看看 printValueTree(JsonRoot) 是怎么做的
    /// printValueTree 是从Json官方Demo中改版过来的
    // printValueTree(JsonRoot);

    /**
    Json::objectValue
    Json::arrayValue
    Json::objectValue
    Json::stringValue
    */

    parse_my_json_step_1(JsonRoot, deqJsonDesc);

    for (it = deqJsonDesc.begin(); it != deqJsonDesc.end(); it++)
    {
        JsonDesc = *it; ///< 浅拷贝

        /// use parse result JsonDesc
        showTAG_JSON_DESC(JsonDesc);

        /** we have get json string element content
        id = id14771, name = name11538, age = age1869, sex = sex19912
        id = id19169, name = name15724, age = age11478, sex = sex29358
        id = id19718, name = name19895, age = age5447, sex = sex21726
        id = id23281, name = name16827, age = age9961, sex = sex491
        id = id25667, name = name26299, age = age17035, sex = sex9894
        id = id26962, name = name24464, age = age5705, sex = sex28145
        id = id292, name = name12382, age = age17421, sex = sex18716
        id = id2995, name = name11942, age = age4827, sex = sex5436
        id = id32391, name = name14604, age = age3902, sex = sex153
        id = id41, name = name18467, age = age6334, sex = sex26500
        */
    }
}

void parse_my_json_step_1(Json::Value& JsonVal, std::deque<TAG_JSON_DESC>& deqJsonDesc)
{
    // Json::objectValue
    std::wstring nameW = L"";
    _ASSERT_EXPR((Json::objectValue == JsonVal.type()), L"(Json::objectValue == JsonRoot.type())");

    Json::Value::Members members(JsonVal.getMemberNames());
    std::sort( members.begin(), members.end() );

    for (Json::Value::Members::iterator it = members.begin(); 
        it != members.end(); 
        ++it)
    {
        const std::string &name = *it;
        nameW = UTF8_2_UNICODE(name);
        parse_my_json_step_2(JsonVal[name], deqJsonDesc);
    }
}

void parse_my_json_step_2(Json::Value& JsonVal, std::deque<TAG_JSON_DESC>& deqJsonDesc)
{
    // Json::arrayValue
    _ASSERT_EXPR((Json::arrayValue == JsonVal.type()), L"(Json::objectValue == JsonRoot.type())");

    int size = JsonVal.size();
    TAG_JSON_DESC   JsonDesc;
    for (int index =0; index < size; ++index)
    {
        static WCHAR buffer[16];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
        _stprintf_s( buffer, sizeof(buffer), L"[%d]", index );
#else
        snpwrintf( buffer, sizeof(buffer), L"[%d]", index );
#endif
        parse_my_json_step_3(JsonVal[index], JsonDesc, index);
    }

    /**
    已经得到 JsonDesc
    -		JsonDesc	{str_id="id14771" str_name="name11538" str_age="age1869" ...}	_tag_json_desc
    +		str_id	"id14771"	std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
    +		str_name	"name11538"	std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
    +		str_age	"age1869"	std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
    +		str_sex	"sex19912"	std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
    */
    deqJsonDesc.push_back(JsonDesc);
}

void parse_my_json_step_3(Json::Value& JsonVal, TAG_JSON_DESC& JsonDesc, int iIndex)
{
    // Json::objectValue
    USES_CONVERSION;
    std::string     str_key = "";
    Json::Value     JsonValTmp;
    size_t          nSize = 0;
    _ASSERT_EXPR((Json::objectValue == JsonVal.type()), L"(Json::objectValue == JsonRoot.type())");

    Json::Value::Members members(JsonVal.getMemberNames());
    nSize = members.size();
    if (nSize > 1)
    {
        std::sort( members.begin(), members.end() );
    }

    _ASSERT_EXPR((1 == nSize), L"(1 == nSize)");
    for (Json::Value::Members::iterator it = members.begin(); 
        it != members.end(); 
        ++it)
    {
        str_key = *it;
        if (0 == str_key.compare(cKeyArray[iIndex]))
        {
            JsonValTmp = JsonVal[str_key.c_str()];
            _ASSERT_EXPR((Json::stringValue == JsonValTmp.type()), L"(Json::stringValue == JsonValTmp.type())");
            switch (iIndex)
            {
            case 0:
                JsonDesc.str_id = A2W(JsonValTmp.asCString());
                break;
            case 1:
                JsonDesc.str_name = A2W(JsonValTmp.asCString());
                break;
            case 2:
                JsonDesc.str_age = A2W(JsonValTmp.asCString());
                break;
            case 3:
                JsonDesc.str_sex = A2W(JsonValTmp.asCString());
                break;
            default:
                _ASSERT_EXPR(0, L"iIndex not on cKeyArray\r\n");
                break;
            }
        }
    }
}

void make_json_array(std::string& strJsonArray)
{
    int i = 0;
    int j = 0;

    std::string         strVal = "";
    std::string         strIdVal = "";

    Json::Value         json_array1;
    Json::Value         json_array2;
    Json::Value         json_item1;

    Json::FastWriter    json_writer;

    strJsonArray = "";

    /** 生成的例子样例
    {
    "id14771":[{"id":"id14771"},{"name":"name11538"},{"age":"age1869"},{"sex":"sex19912"}],
    "id19169":[{"id":"id19169"},{"name":"name15724"},{"age":"age11478"},{"sex":"sex29358"}],
    "id19718":[{"id":"id19718"},{"name":"name19895"},{"age":"age5447"},{"sex":"sex21726"}],
    "id23281":[{"id":"id23281"},{"name":"name16827"},{"age":"age9961"},{"sex":"sex491"}],
    "id25667":[{"id":"id25667"},{"name":"name26299"},{"age":"age17035"},{"sex":"sex9894"}],
    "id26962":[{"id":"id26962"},{"name":"name24464"},{"age":"age5705"},{"sex":"sex28145"}],
    "id292":[{"id":"id292"},{"name":"name12382"},{"age":"age17421"},{"sex":"sex18716"}],
    "id2995":[{"id":"id2995"},{"name":"name11942"},{"age":"age4827"},{"sex":"sex5436"}],
    "id32391":[{"id":"id32391"},{"name":"name14604"},{"age":"age3902"},{"sex":"sex153"}],
    "id41":[{"id":"id41"},{"name":"name18467"},{"age":"age6334"},{"sex":"sex26500"}]
    }
    */

    json_array2.clear();
    for (j = 0; j < MAX_JSON_REC_CNT; j++)
    {
        json_array1.clear();
        for (i = 0; i < (sizeof(cKeyArray) / sizeof(char*)); i++)
        {
            strVal = StringFormatVA("%s%d", cKeyArray[i], rand());
            if (0 == i)
                strIdVal = strVal.c_str();

            json_item1.clear();
            json_item1[cKeyArray[i]] = strVal.c_str();

            json_array1.append(json_item1);
        }

        json_array2[strIdVal.c_str()] = json_array1;
    }

    strJsonArray = json_writer.write(json_array2); 
}

std::wstring StringFormatV(WCHAR * szFormat, ...)
{//入参为格式化的参数列表
    size_t          nStrLen     =   0;
    WCHAR *       pBufMsg     =   NULL;
    std::wstring    strRc;
    va_list         args;

    va_start(args, szFormat);

    nStrLen = _vsntprintf(NULL, 0, szFormat, args);

    pBufMsg = new WCHAR[nStrLen + 1];
    _ASSERT(pBufMsg);
    ::ZeroMemory(pBufMsg, (nStrLen + 1) * sizeof(WCHAR));

    nStrLen = _vsntprintf(pBufMsg, nStrLen, szFormat, args);
    va_end(args);

    strRc = pBufMsg;

    delete []pBufMsg;
    pBufMsg = NULL;

    return strRc;
}

std::string StringFormatVA(char * szFormat, ...)
{//入参为格式化的参数列表
    size_t          nStrLen     =   0;
    char *          pBufMsg     =   NULL;
    std::string    strRc;
    va_list         args;

    va_start(args, szFormat);

    nStrLen = _vsnprintf(NULL, 0, szFormat, args);

    pBufMsg = new char[nStrLen + 1];
    _ASSERT(pBufMsg);
    ::ZeroMemory(pBufMsg, nStrLen + 1);

    nStrLen = _vsnprintf(pBufMsg, nStrLen, szFormat, args);
    va_end(args);

    strRc = pBufMsg;

    delete []pBufMsg;
    pBufMsg = NULL;

    return strRc;
}

BOOL UNICODE_2_UTF8(const WCHAR * pcSrc, std::string & strUtf8)
{
    size_t  nIndex = 0;
    size_t  nLen = 0;
    int     iRc = 0;
    std::string    strOut = "";
    WCHAR cSrc = L'\0';
    char cTemp[8] = {"\0"};

    strUtf8 = "";
    if(NULL == pcSrc)
        return FALSE;

    nLen = _tcslen(pcSrc);
    for (nIndex = 0; nIndex < nLen; nIndex++)
    {
        cSrc = *(pcSrc + nIndex);
        iRc = enc_unicode_to_utf8_one(cSrc, (UCHAR *)(&cTemp[0]), 8);
        if (iRc <= 0)
            return FALSE;
        strUtf8 += cTemp;
    }

    return TRUE;
}

int enc_unicode_to_utf8_one(
    unsigned long unic, 
    unsigned char *pOutput,
    int outSize)
{
    _ASSERT(pOutput != NULL);
    _ASSERT(outSize >= 6);

    if ( unic <= 0x0000007F )
    {
        // * U-00000000 - U-0000007F:  0xxxxxxx
        *pOutput     = (unic & 0x7F);
        return 1;
    }
    else if ( unic >= 0x00000080 && unic <= 0x000007FF )
    {
        // * U-00000080 - U-000007FF:  110xxxxx 10xxxxxx
        *(pOutput+1) = (unic & 0x3F) | 0x80;
        *pOutput     = ((unic >> 6) & 0x1F) | 0xC0;
        return 2;
    }
    else if ( unic >= 0x00000800 && unic <= 0x0000FFFF )
    {
        // * U-00000800 - U-0000FFFF:  1110xxxx 10xxxxxx 10xxxxxx
        *(pOutput+2) = (unic & 0x3F) | 0x80;
        *(pOutput+1) = ((unic >>  6) & 0x3F) | 0x80;
        *pOutput     = ((unic >> 12) & 0x0F) | 0xE0;
        return 3;
    }
    else if ( unic >= 0x00010000 && unic <= 0x001FFFFF )
    {
        // * U-00010000 - U-001FFFFF:  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
        *(pOutput+3) = (unic & 0x3F) | 0x80;
        *(pOutput+2) = ((unic >>  6) & 0x3F) | 0x80;
        *(pOutput+1) = ((unic >> 12) & 0x3F) | 0x80;
        *pOutput     = ((unic >> 18) & 0x07) | 0xF0;
        return 4;
    }
    else if ( unic >= 0x00200000 && unic <= 0x03FFFFFF )
    {
        // * U-00200000 - U-03FFFFFF:  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        *(pOutput+4) = (unic & 0x3F) | 0x80;
        *(pOutput+3) = ((unic >>  6) & 0x3F) | 0x80;
        *(pOutput+2) = ((unic >> 12) & 0x3F) | 0x80;
        *(pOutput+1) = ((unic >> 18) & 0x3F) | 0x80;
        *pOutput     = ((unic >> 24) & 0x03) | 0xF8;
        return 5;
    }
    else if ( unic >= 0x04000000 && unic <= 0x7FFFFFFF )
    {
        // * U-04000000 - U-7FFFFFFF:  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        *(pOutput+5) = (unic & 0x3F) | 0x80;
        *(pOutput+4) = ((unic >>  6) & 0x3F) | 0x80;
        *(pOutput+3) = ((unic >> 12) & 0x3F) | 0x80;
        *(pOutput+2) = ((unic >> 18) & 0x3F) | 0x80;
        *(pOutput+1) = ((unic >> 24) & 0x3F) | 0x80;
        *pOutput     = ((unic >> 30) & 0x01) | 0xFC;
        return 6;
    }

    return 0;
}

BOOL GetJsonString(Json::Value& JsonValue, char* pKey, std::wstring& strValue)
{
    BOOL        bRc = FALSE;
    std::string strTmp = "";

    strValue = L"";
    if (NULL == pKey)
        goto END_GetJsonString;

    if (JsonValue[pKey].isString())
    {
        strTmp = JsonValue[pKey].asCString();
        strValue = UTF8_2_UNICODE(strTmp);
        bRc = TRUE;
    }

END_GetJsonString:
    return bRc;
}

std::wstring UTF8_2_UNICODE(const std::string& strUTF8)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8.c_str(), -1, NULL, 0);
    if(len <= 0)
        return L"";

    std::wstring wStr;
    wStr.resize(len);

    if(MultiByteToWideChar(CP_UTF8, 0, strUTF8.c_str(), -1, (LPWSTR)wStr.c_str(), len) <= 0)
    {
        return L"";
    }

    return wStr;
}

void showTAG_JSON_DESC(const TAG_JSON_DESC& jsonDesc)
{
    std::wstring    strMsg = L"";

    strMsg = StringFormatV(L"id = %s, name = %s, age = %s, sex = %s\r\n",
        jsonDesc.str_id.c_str(),
        jsonDesc.str_name.c_str(),
        jsonDesc.str_age.c_str(),
        jsonDesc.str_sex.c_str());

    _tprintf(strMsg.c_str());
}

void printValueTree(Json::Value &value, const std::wstring &path /* = L"." */ )
{
    USES_CONVERSION;

    switch ( value.type() )
    {
    case Json::nullValue:
        {
            _tprintf(L"%s=null\n", path.c_str() );
        }
        break;
    case Json::intValue:
        {
            _tprintf(L"%s=%s\n", path.c_str(), Json::valueToString(value.asInt()).c_str() );
        }
        break;
    case Json::uintValue:
        {
            _tprintf(L"%s=%s\n", path.c_str(), Json::valueToString(value.asUInt()).c_str() );
        }
        break;
    case Json::realValue:
        {
            _tprintf(L"%s=%s\n", path.c_str(), normalizeFloatingPointStr(value.asDouble()).c_str() );
        }
        break;
    case Json::stringValue:
        {
            _tprintf(L"%s=\"%s\"\n", path.c_str(), UTF8_2_UNICODE(value.asString()).c_str() );
        }
        break;
    case Json::booleanValue:
        {
            _tprintf(L"%s=%s\n", path.c_str(), value.asBool() ? "true" : "false" );
        }
        break;
    case Json::arrayValue:
        {
            _tprintf(L"%s=[]\n", path.c_str() );
            int size = value.size();
            for ( int index =0; index < size; ++index )
            {
                static WCHAR buffer[16];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
                _stprintf_s( buffer, sizeof(buffer), L"[%d]", index );
#else
                snpwrintf( buffer, sizeof(buffer), L"[%d]", index );
#endif
                printValueTree(value[index], path + buffer );
            }
        }
        break;
    case Json::objectValue:
        {
            _tprintf(L"%s={}\n", path.c_str() );
            Json::Value::Members members( value.getMemberNames() );
            std::sort( members.begin(), members.end() );
            std::wstring suffix = *(path.end()-1) == L'.' ? L"" : L".";
            for ( Json::Value::Members::iterator it = members.begin(); 
                it != members.end(); 
                ++it )
            {
                const std::string &name = *it;
                std::wstring nameW = UTF8_2_UNICODE(name);
                printValueTree(value[name], path + suffix + nameW );
            }
        }
        break;
    default:
        break;
    }
}

static std::string normalizeFloatingPointStr( double value )
{
    char buffer[32];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
    sprintf_s( buffer, sizeof(buffer), "%.16g", value );
#else
    snprintf( buffer, sizeof(buffer), "%.16g", value );
#endif
    buffer[sizeof(buffer)-1] = 0;
    std::string s( buffer );
    std::string::size_type index = s.find_last_of( "eE" );
    if ( index != std::string::npos )
    {
        std::string::size_type hasSign = (s[index+1] == '+' || s[index+1] == '-') ? 1 : 0;
        std::string::size_type exponentStartIndex = index + 1 + hasSign;
        std::string normalized = s.substr( 0, exponentStartIndex );
        std::string::size_type indexDigit = s.find_first_not_of( '0', exponentStartIndex );
        std::string exponent = "0";
        if ( indexDigit != std::string::npos ) // There is an exponent different from 0
        {
            exponent = s.substr( indexDigit );
        }
        return normalized + exponent;
    }
    return s;
}


 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值