C++ Client-Side SDK
LaunchDarkly SDK
Loading...
Searching...
No Matches
json_primitives.hpp
1#pragma once
2
3#include <launchdarkly/detail/serialization/json_errors.hpp>
4#include <tl/expected.hpp>
5
6#include <boost/core/ignore_unused.hpp>
7#include <boost/json.hpp>
8
9#include <optional>
10#include <unordered_map>
11
12namespace launchdarkly {
13
14template <typename T>
15tl::expected<std::optional<std::vector<T>>, JsonError> tag_invoke(
16 boost::json::value_to_tag<
17 tl::expected<std::optional<std::vector<T>>, JsonError>> const& unused,
18 boost::json::value const& json_value) {
19 boost::ignore_unused(unused);
20
21 if (json_value.is_null()) {
22 return std::nullopt;
23 }
24
25 if (!json_value.is_array()) {
26 return tl::unexpected(JsonError::kSchemaFailure);
27 }
28
29 auto const& arr = json_value.as_array();
30 std::vector<T> items;
31 items.reserve(arr.size());
32 for (auto const& item : arr) {
33 auto eval_result =
34 boost::json::value_to<tl::expected<std::optional<T>, JsonError>>(
35 item);
36 if (!eval_result.has_value()) {
37 return tl::unexpected(eval_result.error());
38 }
39 auto maybe_val = eval_result.value();
40 if (maybe_val) {
41 items.emplace_back(std::move(maybe_val.value()));
42 }
43 }
44 return items;
45}
46
47tl::expected<std::optional<bool>, JsonError> tag_invoke(
48 boost::json::value_to_tag<
49 tl::expected<std::optional<bool>, JsonError>> const& unused,
50 boost::json::value const& json_value);
51
52tl::expected<std::optional<std::uint64_t>, JsonError> tag_invoke(
53 boost::json::value_to_tag<
54 tl::expected<std::optional<std::uint64_t>, JsonError>> const& unused,
55 boost::json::value const& json_value);
56
57tl::expected<std::optional<std::int64_t>, JsonError> tag_invoke(
58 boost::json::value_to_tag<
59 tl::expected<std::optional<std::int64_t>, JsonError>> const& unused,
60 boost::json::value const& json_value);
61
62tl::expected<std::optional<std::string>, JsonError> tag_invoke(
63 boost::json::value_to_tag<
64 tl::expected<std::optional<std::string>, JsonError>> const& unused,
65 boost::json::value const& json_value);
66
67template <typename K, typename V>
68tl::expected<std::optional<std::unordered_map<K, V>>, JsonError> tag_invoke(
69 boost::json::value_to_tag<
70 tl::expected<std::optional<std::unordered_map<K, V>>, JsonError>> const&
71 unused,
72 boost::json::value const& json_value) {
73 boost::ignore_unused(unused);
74
75 if (json_value.is_null()) {
76 return std::nullopt;
77 }
78 if (!json_value.is_object()) {
79 return tl::unexpected(JsonError::kSchemaFailure);
80 }
81 auto const& obj = json_value.as_object();
82 std::unordered_map<K, V> descriptors;
83 for (auto const& pair : obj) {
84 auto eval_result =
85 boost::json::value_to<tl::expected<std::optional<V>, JsonError>>(
86 pair.value());
87 if (!eval_result) {
88 return tl::unexpected(eval_result.error());
89 }
90 auto const& maybe_val = eval_result.value();
91 if (maybe_val) {
92 descriptors.emplace(pair.key(), std::move(maybe_val.value()));
93 }
94 }
95 return descriptors;
96}
97
107template <typename T>
108tl::expected<T, JsonError> tag_invoke(
109 boost::json::value_to_tag<tl::expected<T, JsonError>> const& unused,
110 boost::json::value const& json_value) {
111 boost::ignore_unused(unused);
112 auto maybe_val =
113 boost::json::value_to<tl::expected<std::optional<T>, JsonError>>(
114 json_value);
115 if (!maybe_val.has_value()) {
116 return tl::unexpected(maybe_val.error());
117 }
118 return maybe_val.value().value_or(T());
119}
120
121} // namespace launchdarkly