nlib
msgpack/json/json.cpp

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

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

一般的にDOMを用いた方が簡単に処理を記述できますが、より多くのメモリを必要とします。 ストリーミングI/Fを用いた場合はその逆です。1つのJSONに対して部分的にDOMを用いて処理を記述することも可能です。
以下がサンプルのソースコードになります。
/*--------------------------------------------------------------------------------*
Project: CrossRoad
Copyright (C)Nintendo All rights reserved.
These coded instructions, statements, and computer programs contain proprietary
information of Nintendo and/or its licensed developers and are protected by
national and international copyright laws. 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.
The content herein is highly confidential and should be handled accordingly.
*--------------------------------------------------------------------------------*/
#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::kEventStartMap) return false;
while ((ev = parser.Next()) != JsonStreamParser::kEventEndMap) {
if (ev != JsonStreamParser::kEventKeyName) return false;
if (strcmp(parser.GetToken().buf, "item") == 0) {
if ((ev = parser.Next()) != JsonStreamParser::kEventStartArray) return false;
while ((ev = parser.Next()) != JsonStreamParser::kEventEndArray) {
if (ev != JsonStreamParser::kEventStartMap) return false;
while ((ev = parser.Next()) != JsonStreamParser::kEventEndMap) {
if (ev != JsonStreamParser::kEventKeyName) 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