jsoncpp.h 4.1 KB

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