#include <json/json.h>
#include <iostream>
#include <string>

struct SerializableType
{
  virtual std::string write() const = 0;
  virtual void read(const std::string& str) = 0;
};

struct Question : public SerializableType
{
  std::string question;
  std::string answer;
  int category = 0;
  void read(const std::string& str) override
  {
    // Deserialisierung: Auslesen aus einem String
    Json::Value jsonObj;
    Json::Reader().parse(str, jsonObj);
    // Abruf der gewünschten Eigenschaften
    question = jsonObj["question"].asString();
    answer = jsonObj["answer"].asString();
    category = jsonObj["category"].asInt();
  }
  std::string write() const override
  {
    // Serialisierung: Abspeichern in einem String
    Json::StreamWriterBuilder factory;
    Json::Value jsonObj;
    jsonObj["question"] = question;
    jsonObj["answer"] = answer;
    jsonObj["category"] = category;
    return Json::writeString(factory, jsonObj);
  }
};

struct User : public SerializableType
{
  std::string name;
  int id = 0;
  void read(const std::string& str)  override
  {
    Json::Value jsonObj;
    Json::Reader().parse(str, jsonObj);
    name = jsonObj["name"].asString();
    id = jsonObj["id"].asInt();
  }
  std::string write() const override
  {
    Json::StreamWriterBuilder factory;
    Json::Value jsonObj;
    jsonObj["name"] = name;
    jsonObj["id"] = id;
    return Json::writeString(factory, jsonObj);
  }
};

void printOnConsole(const SerializableType& type)
{
  std::cout << type.write() << std::endl;
}

int main()
{
  Question q1;
  q1.question = "Was macht es?";
  q1.answer = "Es leuchtet blau";
  q1.category = 2;
  std::cout << q1.write() << std::endl;
  Question q2;
  q2.read(q1.write());
  std::cout << q2.write() << std::endl;

  User user;
  user.name = "Manfred";
  user.id = 17;
  std::cout << user.write() << std::endl;

  printOnConsole(q1);
  printOnConsole(q2);
  printOnConsole(user);
  return 0;
}
