rippled
Loading...
Searching...
No Matches
json_get_or_throw.h
1#pragma once
2
3#include <xrpl/basics/Buffer.h>
4#include <xrpl/basics/StringUtilities.h>
5#include <xrpl/basics/contract.h>
6#include <xrpl/json/json_value.h>
7#include <xrpl/protocol/SField.h>
8
9#include <charconv>
10#include <exception>
11#include <optional>
12
13namespace Json {
15{
16 char const* const key;
19 {
20 }
21 char const*
22 what() const noexcept override
23 {
24 if (msg.empty())
25 {
26 msg = std::string("Missing json key: ") + key;
27 }
28 return msg.c_str();
29 }
30};
31
33{
34 char const* const key;
38 : key{k.c_str()}, expectedType{std::move(et)}
39 {
40 }
41 char const*
42 what() const noexcept override
43 {
44 if (msg.empty())
45 {
46 msg = std::string("Type mismatch on json key: ") + key +
47 "; expected type: " + expectedType;
48 }
49 return msg.c_str();
50 }
51};
52
53template <class T>
54T
55getOrThrow(Json::Value const& v, xrpl::SField const& field)
56{
57 static_assert(sizeof(T) == -1, "This function must be specialized");
58}
59
60template <>
61inline std::string
62getOrThrow(Json::Value const& v, xrpl::SField const& field)
63{
64 using namespace xrpl;
65 Json::StaticString const& key = field.getJsonName();
66 if (!v.isMember(key))
67 Throw<JsonMissingKeyError>(key);
68
69 Json::Value const& inner = v[key];
70 if (!inner.isString())
71 Throw<JsonTypeMismatchError>(key, "string");
72 return inner.asString();
73}
74
75// Note, this allows integer numeric fields to act as bools
76template <>
77inline bool
78getOrThrow(Json::Value const& v, xrpl::SField const& field)
79{
80 using namespace xrpl;
81 Json::StaticString const& key = field.getJsonName();
82 if (!v.isMember(key))
83 Throw<JsonMissingKeyError>(key);
84 Json::Value const& inner = v[key];
85 if (inner.isBool())
86 return inner.asBool();
87 if (!inner.isIntegral())
88 Throw<JsonTypeMismatchError>(key, "bool");
89
90 return inner.asInt() != 0;
91}
92
93template <>
94inline std::uint64_t
95getOrThrow(Json::Value const& v, xrpl::SField const& field)
96{
97 using namespace xrpl;
98 Json::StaticString const& key = field.getJsonName();
99 if (!v.isMember(key))
100 Throw<JsonMissingKeyError>(key);
101 Json::Value const& inner = v[key];
102 if (inner.isUInt())
103 return inner.asUInt();
104 if (inner.isInt())
105 {
106 auto const r = inner.asInt();
107 if (r < 0)
108 Throw<JsonTypeMismatchError>(key, "uint64");
109 return r;
110 }
111 if (inner.isString())
112 {
113 auto const s = inner.asString();
114 // parse as hex
115 std::uint64_t val = 0;
116
117 auto [p, ec] = std::from_chars(s.data(), s.data() + s.size(), val, 16);
118
119 if (ec != std::errc() || (p != s.data() + s.size()))
120 Throw<JsonTypeMismatchError>(key, "uint64");
121 return val;
122 }
123 Throw<JsonTypeMismatchError>(key, "uint64");
124}
125
126template <>
127inline xrpl::Buffer
128getOrThrow(Json::Value const& v, xrpl::SField const& field)
129{
130 using namespace xrpl;
131 std::string const hex = getOrThrow<std::string>(v, field);
132 if (auto const r = strUnHex(hex))
133 {
134 // TODO: mismatch between a buffer and a blob
135 return Buffer{r->data(), r->size()};
136 }
137 Throw<JsonTypeMismatchError>(field.getJsonName(), "Buffer");
138}
139
140// This function may be used by external projects (like the witness server).
141template <class T>
143getOptional(Json::Value const& v, xrpl::SField const& field)
144{
145 try
146 {
147 return getOrThrow<T>(v, field);
148 }
149 catch (...)
150 {
151 }
152 return {};
153}
154
155} // namespace Json
T c_str(T... args)
Lightweight wrapper to tag static string.
Definition json_value.h:44
Represents a JSON value.
Definition json_value.h:130
Int asInt() const
bool isString() const
UInt asUInt() const
std::string asString() const
Returns the unquoted string value.
bool isBool() const
bool isIntegral() const
bool asBool() const
bool isUInt() const
bool isMember(char const *key) const
Return true if the object has a member named key.
bool isInt() const
Like std::vector<char> but better.
Definition Buffer.h:16
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition Buffer.h:128
Identifies fields.
Definition SField.h:126
T empty(T... args)
T from_chars(T... args)
JSON (JavaScript Object Notation).
Definition json_errors.h:5
std::optional< T > getOptional(Json::Value const &v, xrpl::SField const &field)
xrpl::AccountID getOrThrow(Json::Value const &v, xrpl::SField const &field)
Definition AccountID.h:111
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
char const * what() const noexcept override
JsonMissingKeyError(Json::StaticString const &k)
char const * what() const noexcept override
JsonTypeMismatchError(Json::StaticString const &k, std::string et)