209 lines
5.8 KiB
C++
209 lines
5.8 KiB
C++
#include <JJX/JJX.hpp>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
|
|
using namespace JJX;
|
|
|
|
/// Open a text file and return the contents.
|
|
std::string read_file(const std::string& file_path)
|
|
{
|
|
std::ifstream file(file_path, std::ios::binary);
|
|
if (!file)
|
|
throw std::runtime_error("We couldn't find the file: " + file_path);
|
|
|
|
std::streamsize file_size;
|
|
file.seekg(0, std::ios::end);
|
|
file_size = file.tellg();
|
|
file.seekg(0, std::ios::beg);
|
|
|
|
std::string file_content(file_size, '\0');
|
|
file.read(&file_content[0], file_size);
|
|
file.close();
|
|
|
|
return file_content;
|
|
}
|
|
|
|
|
|
void parse_json_file(const std::string& file_path) {
|
|
auto file_content = read_file(file_path);
|
|
|
|
auto [text, parse_error] = json::parse(file_content);
|
|
if (!parse_error.empty())
|
|
std::cerr << "Error while parsing json: " << parse_error << std::endl;
|
|
|
|
std::cout << json::deparse(text) << std::endl;
|
|
}
|
|
|
|
struct Vector3
|
|
{
|
|
float x, y, z;
|
|
};
|
|
|
|
|
|
/// Creates json array out of Vector3 type.
|
|
json::value vector3_to_json(const Vector3& v) {
|
|
//auto x = json::number(input.x);
|
|
//auto y = json::number(input.y);
|
|
//auto z = json::number(input.z);
|
|
return json::array({v.x, v.y, v.z});
|
|
}
|
|
|
|
/// Creates Vector3 type out of json array object.
|
|
Vector3 json_to_vector3(const json::value& obj) {
|
|
Vector3 value;
|
|
|
|
value.x = obj.array->at(0).number.value_or(0);
|
|
value.y = obj.array->at(1).number.value_or(0);
|
|
value.z = obj.array->at(2).number.value_or(0);
|
|
|
|
return {value};
|
|
}
|
|
|
|
/// I personally recommend using the following signatures for serializing and deserializing your objects
|
|
/// as this will be considered the standard interface for the library, going forward.
|
|
/// It may end up being a template so don't worry so much about inheriting these structs, specifically.
|
|
|
|
struct json_serializable {
|
|
// json::value serialize() const { ... }
|
|
virtual json::value serialize() const = 0; //{ /* Create a json::value, add data, and return. */; };
|
|
};
|
|
|
|
struct json_deserializable {
|
|
explicit json_deserializable(const json::value&) = delete;
|
|
};
|
|
|
|
struct json_convertible : json_serializable, json_deserializable {};
|
|
|
|
struct product_info
|
|
{
|
|
[[nodiscard]] json::value serialize() const;
|
|
product_info() = default;
|
|
/// @schema object {string category, string description, boolean is_available, string name, number price, array[@review] reviews}
|
|
/// @note This class design assumes all entries in `reviews` are serializable to @struct review,
|
|
///
|
|
explicit product_info(const json::value& jv);
|
|
|
|
struct rating_metrics {
|
|
double average;
|
|
int total;
|
|
};
|
|
|
|
/// @schema { rating : number, review_text : string, user : string }
|
|
struct review {
|
|
[[nodiscard]] json::value serialize() const;
|
|
explicit review(const json::value& jv);
|
|
|
|
int rating;
|
|
std::string review_text;
|
|
std::string user;
|
|
};
|
|
|
|
std::string category;
|
|
std::string description;
|
|
bool is_available;
|
|
std::string manufacturer;
|
|
std::string name;
|
|
double price;
|
|
std::string product_id;
|
|
rating_metrics ratings;
|
|
std::string release_date;
|
|
std::vector<review> reviews;
|
|
};
|
|
|
|
json::value product_info::serialize() const {
|
|
json::object root;
|
|
root += {"category", this->category};
|
|
root += {"manufacturer", this->manufacturer};
|
|
root += {"is_available", this->is_available};
|
|
root += {"description", this->description};
|
|
root += {"name", this->name};
|
|
|
|
auto review_list = json::array();
|
|
for (auto& rev : this->reviews)
|
|
review_list += rev.serialize();
|
|
|
|
root["ratings"] = {
|
|
{"average", this->ratings.average},
|
|
{"total", this->ratings.total}
|
|
};
|
|
|
|
root += {"reviews", review_list};
|
|
root += {"taters", 5.0};
|
|
|
|
return root;
|
|
}
|
|
|
|
product_info::product_info(const json::value &jv) {
|
|
if (jv.type != json::value_type::object)
|
|
throw std::runtime_error("Malformed JSON for product info!");
|
|
|
|
auto jvo = jv.as_object();
|
|
|
|
this->category = jvo["category"].string.value();
|
|
this->description = jvo["description"].string.value();
|
|
this->is_available = jvo["is_available"].boolean.value();
|
|
this->manufacturer = jvo["manufacturer"].string.value();
|
|
this->name = jvo["name"].string.value();
|
|
this->price = double(jvo["price"]);
|
|
|
|
for (auto& review_json : jvo["reviews"].as_array()) {
|
|
this->reviews.emplace_back(review_json);
|
|
}
|
|
|
|
this->ratings.average = jvo["ratings"]["average"].number.value();
|
|
this->ratings.total = jvo["ratings"]["total"].number.value();
|
|
|
|
}
|
|
|
|
json::value product_info::review::serialize() const {
|
|
json::object obj = json::object();
|
|
obj["rating"] = json::number(rating);
|
|
obj["review_text"] = json::string(review_text);
|
|
obj["user"] = json::string(user);
|
|
return obj;
|
|
}
|
|
|
|
product_info::review::review(const json::value &jv) {
|
|
if (jv.type != json::value_type::object)
|
|
throw std::runtime_error("Malformed JSON for review!");
|
|
}
|
|
|
|
void test_product_info()
|
|
{
|
|
std::cout << "Testing parsing of product_info file." << std::endl;
|
|
//parse_json_file("../samples/product_info.json");
|
|
auto file_contents = read_file("../samples/product_info.json");
|
|
|
|
auto [text, err] = json::parse(file_contents);
|
|
|
|
if (!err.empty()) {
|
|
std::cerr << err << std::endl;
|
|
return;
|
|
}
|
|
|
|
std::cout << "Testing deserialization of product_info json." << std::endl;
|
|
// Construct from json object.
|
|
product_info test(text);
|
|
|
|
std::cout << "Testing serialization of product_info struct." << std::endl;
|
|
|
|
json::value result = test.serialize();
|
|
|
|
result.convert_descendants();
|
|
std::cout << json::deparse(result);
|
|
}
|
|
|
|
void test_tile_data() {
|
|
//parse_json_file("../samples/tiles.json");
|
|
}
|
|
|
|
void test_widgets() {
|
|
|
|
}
|
|
|
|
// Some progress has been made on small scale.
|
|
int main(int argc, char* argv[]) {
|
|
test_product_info();
|
|
test_tile_data();
|
|
}
|