nlib
msgpack/json/json.cpp

DOM(MpObject)を用いたJSONの読み書きと、ストリーミングI/Fを用いたJSONの読み書きを行うサンプルです。 前者は以下のようなことを行っています。

後者は以下のようなことを行っています。

一般的にDOMを用いた方が簡単に処理を記述できますが、より多くのメモリを必要とします。 ストリーミングI/Fを用いた場合はその逆です。1つのJSONに対して部分的にDOMを用いて処理を記述することも可能です。
以下がサンプルのソースコードになります。
/*---------------------------------------------------------------------------*
Project: CrossRoad
Copyright (C)2012-2016 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
#include "nn/nlib/msgpack/JsonStreamParser.h"
#include "nn/nlib/msgpack/JsonStreamGenerator.h"
#include "nn/nlib/Nlist.h"
using nlib_ns::msgpack::MpObject;
using nlib_ns::msgpack::JsonStreamParser;
using nlib_ns::msgpack::JsonStreamGenerator;
const char jsontext[] =
"{ \"item\": ["
"{\"itemCode\":91, \"itemName\" : \"ramen with salt based soup\", \"itemPrice\":300},"
"{\"itemCode\":94, \"itemName\" : \"ramen with miso based soup\", \"itemPrice\":290}, "
"{\"itemCode\":95, \"itemName\" : \"ramen with a pork bone broth\", \"itemPrice\":320} "
"] } ";
bool ReadModifyWriteJsonByDom() {
UniquePtr<MpObject> obj;
// Reads the menu data in JSON.
if (JsonStreamParser::Parse(obj, jsontext) != 0) return false;
// You want to raise the prices.
MpObject* price;
int val;
MpObject* items = obj->GetMapItem("item");
if (!items) return false;
MpObject* salt = items->GetArrayItem(0);
if (!salt) return false;
price = salt->GetMapItem("itemPrice");
if (!price) return false;
if (nlib_is_error(price->Unbox(&val))) return false; // Unboxes 'price' and retrieve an integer value.
val += 500; // Changes the price
if (nlib_is_error(price->Box(val))) return false; // Boxes 'val' and updates 'price'.
MpObject* miso = items->GetArrayItem(1);
if (!miso) return false;
price = miso->GetMapItem("itemPrice");
if (!price) return false;
if (nlib_is_error(price->Unbox(&val))) return false;
val += 500;
price->Box(val); // Boxing primitive objects never returns an error.
MpObject* pork = items->GetArrayItem(2);
if (!pork) return false;
price = pork->GetMapItem("itemPrice");
if (!price) return false;
if (nlib_is_error(price->Unbox(&val))) return false;
val += 500;
// You can use the assignment operators instead of boxing
// when you box primitive objects.
*price = val;
// Writes the menu data in JSON.
char str[1024];
if (JsonStreamGenerator::Generate(NULL, str, *obj.get()) != 0) return false;
nlib_printf("%s\n", str);
return true;
}
bool ReadAndWritePriceJsonByStreaming() {
JsonStreamParser parser;
MemoryInputStream istr(jsontext);
if (nlib_is_error(parser.Init())) return false;
if (nlib_is_error(parser.Open(&istr))) return false;
Nlist<int> prices;
JsonStreamParser::Event ev;
if ((ev = parser.Next()) != JsonStreamParser::EVENT_START_MAP) return false;
while ((ev = parser.Next()) != JsonStreamParser::EVENT_END_MAP) {
if (ev != JsonStreamParser::EVENT_KEY_NAME) return false;
if (strcmp(parser.GetToken().buf, "item") == 0) {
if ((ev = parser.Next()) != JsonStreamParser::EVENT_START_ARRAY) return false;
while ((ev = parser.Next()) != JsonStreamParser::EVENT_END_ARRAY) {
if (ev != JsonStreamParser::EVENT_START_MAP) return false;
while ((ev = parser.Next()) != JsonStreamParser::EVENT_END_MAP) {
if (ev != JsonStreamParser::EVENT_KEY_NAME) return false;
if (strcmp(parser.GetToken().buf, "itemPrice") == 0) {
ev = parser.Next();
int num;
if (nlib_is_error(JsonStreamParser::ToInt32(parser.GetToken(), &num)))
return false;
prices.push_back(num);
} else {
if (nlib_is_error(parser.Skip())) return false;
}
}
}
} else {
if (nlib_is_error(parser.Skip())) return false;
}
}
JsonStreamGenerator gen;
char str[1024];
MemoryOutputStream ostr(str);
if (nlib_is_error(gen.Init())) return false;
if (nlib_is_error(gen.Open(&ostr))) return false;
size_t prices_size = prices.size();
gen.StartArray(prices_size);
for (size_t i = 0; i < prices_size; ++i) {
gen.Int32(prices[i]);
}
gen.EndArray();
if (nlib_is_error(gen)) return false;
gen.Close();
if (nlib_is_error(ostr.Write('\0'))) return false;
nlib_printf("%s\n", str);
return true;
}
bool SampleMain(int, char**) {
return ReadModifyWriteJsonByDom() && ReadAndWritePriceJsonByStreaming();
}
NLIB_MAINFUNC