问题
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