问题
How can I parse the input json inside this file, especially for the accuracy
, secondary
and flags
properties?
https://github.com/smogon/pokemon-showdown/blob/master/data/moves.js
They are type composition of optional
and variant
.
Though only the full example can surface the problem in a clearer way, a minimal starting point example would be this one:
[
{},
{
"secondary": false
},
{
"secondary": {
"chance": 10,
"boosts": {
"spd": -1
}
}
},
{
"secondary": {
"chance": 30,
"volatileStatus": "flinch"
}
},
{
"secondary": {
"chance": 30
}
},
{
"secondary": {
"chance": 10,
"self": {
"boosts": {
"atk": 1,
"def": 1,
"spa": 1,
"spd": 1,
"spe": 1
}
}
}
},
{
"secondary": {
"chance": 10,
"status": "brn"
}
},
{
"secondary": {
"chance": 50,
"self": {
"boosts": {
"def": 2
}
}
}
},
{
"secondary": {
"chance": 100,
"self": {}
}
},
{
"secondary": {
"chance": 50,
"boosts": {
"accuracy": -1
}
}
}
]
The expected output can be but not limited to:
- parsed object which has more structure, such that we can access by key(if it exists)
- it has dynamic structure so we can check key existence during run time. For example, "boosts" has only a finite number(<10) of possible keys.
For your convenience, you can attach this snippet to the end of the js file and run it using node move.js
. Two valid json files will be saved to your disk. One is a list of json objects while the other is an object with string as key.
var fs = require('fs');
fs.writeFile("moves_object.json", JSON.stringify(BattleMovedex), function(err) {}); // 1. save a json object with string key
var jsonList = []
for (var key of Object.keys(BattleMovedex)) {
jsonList.push(BattleMovedex[key]);
}
fs.writeFile("moves.json", JSON.stringify(jsonList), function(err) { // 2. save as a list of json object
if (err) {
console.log(err);
}
});
In c++(17/20), there are previous attempts here:
https://github.com/nlohmann/json/issues/1281
https://github.com/nlohmann/json/issues/1910
https://github.com/nlohmann/json/issues/1261
Here is a boiler plate taking care of simple optional fields you can begin with:
#include <nlohmann/json.hpp>
#include <iostream>
#include <iomanip>
#include <optional>
using nlohmann::json;
struct json_test_entry
{
std::string cbor;
std::string hex;
bool roundtrip;
std::optional<std::string> diagnostic = std::nullopt;
};
void to_json(nlohmann::json &j, const json_test_entry &p)
{
j = json{
{ "cbor", p.cbor }, { "hex", p.hex }, { "roundtrip", p.roundtrip }
};
// assuming you only want a "diagnostic" key if there is an actual value;
// if not, store a nullptr and adjust the from_json accordingly
if (p.diagnostic != std::nullopt)
{
j["diagnostic"] = p.diagnostic.value();
}
}
void from_json(const nlohmann::json &j, json_test_entry &p)
{
p.cbor = j.at("cbor").get< std::string >();
p.hex = j.at("hex").get< std::string >();
p.roundtrip = j.at("roundtrip").get< bool >();
// if we also allow "null" values, then we need to add an "is_string()"
// check
if (j.count("diagnostic") != 0)
{
p.diagnostic = j.at("diagnostic").get< std::string >();
}
}
int main()
{
auto j = R"([
{
"cbor" : "GBk=",
"hex" : "1819",
"roundtrip" : true,
"decoded" : 25
},
{
"cbor" : "+T4A",
"hex" : "f93e00",
"roundtrip" : true,
"decoded" : 1.5
},
{ "cbor" : "YsO8",
"hex" : "62c3bc",
"roundtrip" : true,
"decoded" : "ü"
},
{ "cbor" : "+X4A",
"hex" : "f97e00",
"roundtrip" : true,
"diagnostic" : "NaN"
},
{
"cbor" : "nwGCAgOfBAX//w==",
"hex" : "9f018202039f0405ffff",
"roundtrip" : false,
"decoded" : [ 1, [ 2, 3 ], [ 4, 5 ] ]
},
{
"cbor" : "gmFhv2FiYWP/",
"hex" : "826161bf61626163ff",
"roundtrip" : false,
"decoded" : [ "a", { "b" : "c" } ]
}
])"_json;
// roundtrip and preserves "diagnostic" entries
std::vector<json_test_entry> v = j;
json k = v;
std::cout << std::setw(2) << k << std::endl;
}
来源:https://stackoverflow.com/questions/59919496/how-to-parse-json-file-with-type-composition-of-stdoptional-and-stdvariant