stephenberry / glaze

Extremely fast, in memory, JSON and interface library for modern C++
MIT License
1.01k stars 105 forks source link

Support std::variant<...,std::variant<...> > #1092

Open shiretu opened 1 month ago

shiretu commented 1 month ago

Hi all,

Here is a patch that allows us to support variant of variant, each having tagged keys:

diff --git a/include/glaze/json/read.hpp b/include/glaze/json/read.hpp
index d13ef99..d8b91b8 100644
--- a/include/glaze/json/read.hpp
+++ b/include/glaze/json/read.hpp
@@ -2239,9 +2239,14 @@ namespace glz
                                        [&](auto&& v) {
                                           using V = std::decay_t<decltype(v)>;
                                           constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
-                                          if constexpr (is_object) {
-                                             from_json<V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
-                                                                                                             end);
+                                          if constexpr (is_variant<V>) {
+                                             from_json<V>::template op<Options>(v, ctx, std::prev(it), end);
+                                          }
+                                          else {
+                                             if constexpr (is_object) {
+                                                from_json<V>::template op<opening_handled<Opts>(), tag_literal>(
+                                                   v, ctx, it, end);
+                                             }
                                           }
                                        },
                                        value);
shiretu commented 1 month ago

More info:

using subscribed = std::variant<subscribed_v4_orderbook, subscribed_v4_subaccounts>;
template <> struct glz::meta<subscribed> {
  static constexpr std::string_view tag = "channel";
  static constexpr auto ids = std::array{"v4_orderbook", "v4_subaccounts"};
};

using ws_message_type = std::variant<connected, subscribed, channel_data>;
template <> struct glz::meta<ws_message_type> {
  static constexpr std::string_view tag = "type";
  static constexpr auto ids = std::array{"connected", "subscribed", "channel_data"};
};

that work properly now: it switches on type and then on channel

shiretu commented 1 month ago

created this PR: https://github.com/stephenberry/glaze/pull/1098 which also includes fixes for issue https://github.com/stephenberry/glaze/issues/1096