从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;
}