jsoncpp.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #pragma once
  2. #include <type_traits>
  3. #include <json/reader.h>
  4. #include <json/value.h>
  5. #include <jvalidate/adapter.h>
  6. #include <jvalidate/detail/expect.h>
  7. #include <jvalidate/detail/number.h>
  8. #include <jvalidate/detail/simple_adapter.h>
  9. #include <jvalidate/enum.h>
  10. namespace jvalidate::adapter {
  11. template <> inline bool load_stream(std::istream & in, Json::Value & out) {
  12. Json::CharReaderBuilder builder;
  13. std::string error;
  14. bool good = Json::parseFromStream(builder, in, &out, &error);
  15. EXPECT_M(good, "Failed to load JSON: " << error);
  16. return good;
  17. }
  18. template <typename JSON> class JsonCppAdapter;
  19. template <> struct AdapterTraits<Json::Value> {
  20. template <typename JSON> using Adapter = adapter::JsonCppAdapter<JSON>;
  21. using ConstAdapter = adapter::JsonCppAdapter<Json::Value const>;
  22. static Json::Value const & const_empty() {
  23. static Json::Value const g_value;
  24. return g_value;
  25. }
  26. };
  27. template <typename JSON> class JsonCppObjectAdapter : public detail::SimpleObjectAdapter<JSON> {
  28. public:
  29. using JsonCppObjectAdapter::SimpleObjectAdapter::SimpleObjectAdapter;
  30. bool contains(std::string const & key) const { return this->const_value().isMember(key); }
  31. JsonCppAdapter<JSON> operator[](std::string const & key) const {
  32. return this->value() ? &(*this->value())[key] : nullptr;
  33. }
  34. void assign(std::string const & key, Const const & frozen) const
  35. requires(not std::is_const_v<JSON>)
  36. {
  37. (*this)[key].assign(frozen);
  38. }
  39. };
  40. template <typename JSON> class JsonCppAdapter final : public detail::SimpleAdapter<JSON> {
  41. public:
  42. using JsonCppAdapter::SimpleAdapter::SimpleAdapter;
  43. Type type() const {
  44. using jvalidate::detail::fits_in_integer;
  45. switch (const_value().type()) {
  46. case Json::nullValue:
  47. return Type::Null;
  48. case Json::booleanValue:
  49. return Type::Boolean;
  50. case Json::realValue:
  51. // Not strictly necessary - Validation code will safely handle this too
  52. return fits_in_integer(const_value().asDouble()) ? Type::Integer : Type::Number;
  53. case Json::stringValue:
  54. return Type::String;
  55. case Json::arrayValue:
  56. return Type::Array;
  57. case Json::objectValue:
  58. return Type::Object;
  59. case Json::intValue:
  60. return Type::Integer;
  61. case Json::uintValue:
  62. return fits_in_integer(const_value().asUInt64()) ? Type::Integer : Type::Number;
  63. }
  64. }
  65. bool as_boolean() const { return const_value().asBool(); }
  66. int64_t as_integer() const { return const_value().asInt64(); }
  67. double as_number() const { return const_value().asDouble(); }
  68. std::string as_string() const { return const_value().asString(); }
  69. JsonCppObjectAdapter<JSON> as_object() const { return value(); }
  70. static std::string key(auto it) { return it.key().asString(); }
  71. using detail::SimpleAdapter<JSON>::assign;
  72. void assign(Adapter const & adapter) const
  73. requires(not std::is_const_v<JSON>)
  74. {
  75. switch (adapter.type()) {
  76. case Type::Null:
  77. *value() = Json::nullValue;
  78. return;
  79. case Type::Boolean:
  80. *value() = adapter.as_boolean();
  81. return;
  82. case Type::Integer:
  83. *value() = adapter.as_integer();
  84. return;
  85. case Type::Number:
  86. *value() = adapter.as_number();
  87. return;
  88. case Type::String:
  89. *value() = adapter.as_string();
  90. return;
  91. case Type::Array:
  92. adapter.apply_array([this, index = 0](Adapter const & elem) mutable {
  93. JsonCppAdapter((*value())[index]).assign(elem);
  94. ++index;
  95. return Status::Accept;
  96. });
  97. return;
  98. case Type::Object:
  99. adapter.apply_object([this](std::string const & key, Adapter const & elem) {
  100. JsonCppAdapter((*value())[key]).assign(elem);
  101. return Status::Accept;
  102. });
  103. return;
  104. }
  105. }
  106. public:
  107. using JsonCppAdapter::SimpleAdapter::const_value;
  108. using JsonCppAdapter::SimpleAdapter::value;
  109. };
  110. }