サンプルアプリのJsonParserAppを見る。
■JsonForm.cpp
void JsonForm::ParseAndDisplay(void)
// なるべく簡略化したいのでエラー処理はコメントアウトしておく。
// fileを読み込み専用で開く。
File file;
String filePath = App::GetInstance()->GetAppRootPath() + L"data/jsonSample.json";
result r = file.Construct(filePath, L"r");
#TryReturnVoid(r == E_SUCCESS, "file construction failure with [%s]", GetErrorMessage(r));
FileAttributes att;
r = File::GetAttributes(filePath, att);
#TryReturnVoid(r == E_SUCCESS, "file GetAttributes failure with [%s]", GetErrorMessage(r));
long long size = att.GetFileSize();
#TryReturnVoid(size > 0, "file does not contain valid data, size of file [%ld]", size);
ByteBuffer buf;
r = buf.Construct(size + 1);// fileサイズ+1で初期化
#TryReturnVoid(r == E_SUCCESS, "bytebuffer construct failure with [%s]", GetErrorMessage(r));
r = file.Read(buf);// fileを読み込む
#TryReturnVoid(r == E_SUCCESS, "file read failure with [%s]", GetErrorMessage(r));
// 読み込んだデータをJSONにパース
IJsonValue* pJson = JsonParser::ParseN(buf);
TryCatch(pJson, , "ParseN failed with [%s]", GetErrorMessage(GetLastResult()));
AppLog("Before traverse %d", _pList->GetItemCount());
_pJsonKeyList->RemoveAll(true);
_pValueList->RemoveAll(true);
TraverseFunction(pJson);
AppLog("After traverse");
fileにclose的なものがないけどいいのかな。
void JsonForm::TraverseFunction(IJsonValue* pValue)
パースしたIJsonValueのオブジェクトを実際にどう扱うか見てみる。このメソッドは、pValue->GetType()で分岐してある。typeによっては自身を呼び出し再帰処理している。
FWebJsonIJsonValue.h
jsonの値の型は以下のように定義されている。
enum JsonType
{
JSON_TYPE_STRING, /**< The JSON string type*/
JSON_TYPE_NUMBER, /**< The JSON number type*/
JSON_TYPE_OBJECT, /**< The JSON object type*/
JSON_TYPE_ARRAY, /**< The JSON array type*/
JSON_TYPE_BOOL, /**< The JSON bool type*/
JSON_TYPE_NULL /**< The JSON null type*/
};
nullの時
TryReturnVoid(_pList, "_pList is null");
TryReturnVoid(pValue, "input jsonvalue pointer is null");
オブジェクトの時
Mapにしてkeyとvalueを取り出し、valueを引き数にして再帰呼び出ししている。
case JSON_TYPE_OBJECT:
{
JsonObject* pObject = static_cast< JsonObject* >(pValue);
IMapEnumeratorT< const String*, IJsonValue* >* pMapEnum = pObject->GetMapEnumeratorN();
while (pMapEnum->MoveNext() == E_SUCCESS)
{
const String* key = null;
IJsonValue* value = null;
pMapEnum->GetKey(key);
String* pListKey = new (std::nothrow) String(*key);
_pJsonKeyList->Add(*pListKey);
String* pStr = null;
_isArray = 0;
pMapEnum->GetValue(value);
if (value->GetType() == JSON_TYPE_OBJECT)
{
pStr = new (std::nothrow) String("Value is an Object");
_pValueList->Add(*pStr);
}
else if (value->GetType() == JSON_TYPE_ARRAY)
{
pStr = new (std::nothrow) String("Value is an Array");
_pValueList->Add(*pStr);
}
TraverseFunction(value);
}
delete pMapEnum;
}
break;
文字列の場合
_pValueListに追加している。
case JSON_TYPE_STRING:
{
JsonString* pVal = static_cast< JsonString* >(pValue);
if (_isArray == 0)
{
String* pStr = new (std::nothrow) String(*pVal);
_pValueList->Add(*pStr);
}
}
break;
配列の場合
keyとvalueを取り出し、valueを引き数にして再帰呼び出ししている。
case JSON_TYPE_ARRAY:
{
JsonArray* pJsonArray = static_cast< JsonArray* >(pValue);
pJsonArray->GetCount();
IEnumeratorT< IJsonValue* >* pEnum = pJsonArray->GetEnumeratorN();
while (pEnum->MoveNext() == E_SUCCESS)
{
IJsonValue* pValue = null;
pEnum->GetCurrent(pValue);
if ((pValue->GetType() == JSON_TYPE_STRING) || (pValue->GetType() == JSON_TYPE_NUMBER) || (pValue->GetType() == JSON_TYPE_BOOL) || (pValue->GetType() == JSON_TYPE_NULL))
_isArray = 1;
TraverseFunction(pValue);
}
delete pEnum;
}
break;
数値の場合
JsonNumberをtoStringして文字列にし、_pValueListにaddしている。
case JSON_TYPE_NUMBER:
{
JsonNumber* pVal = static_cast< JsonNumber* >(pValue);
String* pStr = new (std::nothrow) String((pVal->ToString()));
if (_isArray == 0)
_pValueList->Add(*pStr);
}
break;
真偽値の場合
条件分岐して、文字列を_pValueListにaddするようにしている。
case JSON_TYPE_BOOL:
{
String* pStr = null;
JsonBool* pVal = static_cast< JsonBool* >(pValue);
if (*pVal == true)
pStr = new (std::nothrow) String("true");
else
pStr = new (std::nothrow) String("false");
if (_isArray == 0)
_pValueList->Add(*pStr);
}
break;
nullの場合
nullという文字列を_pValueListにaddするようにしている。
case JSON_TYPE_NULL:
{
String* pStr = null;
pStr = new (std::nothrow) String("null");
if (_isArray == 0)
_pValueList->Add(*pStr);
}
break;
読むのが面倒だったがC++の基本が分かる良いコードだった。