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