/ src / common / utils / json.h
json.h
  1  #pragma once
  2  
  3  #include <winrt/Windows.Foundation.h>
  4  #include <winrt/Windows.Foundation.Collections.h>
  5  #include <winrt/Windows.Data.Json.h>
  6  
  7  #include <optional>
  8  #include <fstream>
  9  
 10  namespace json
 11  {
 12      using namespace winrt::Windows::Data::Json;
 13  
 14      inline std::optional<JsonObject> from_file(std::wstring_view file_name)
 15      {
 16          try
 17          {
 18              std::ifstream file(file_name.data(), std::ios::binary);
 19              if (file.is_open())
 20              {
 21                  using isbi = std::istreambuf_iterator<char>;
 22                  std::string obj_str{ isbi{ file }, isbi{} };
 23                  return JsonValue::Parse(winrt::to_hstring(obj_str)).GetObjectW();
 24              }
 25              return std::nullopt;
 26          }
 27          catch (...)
 28          {
 29              return std::nullopt;
 30          }
 31      }
 32  
 33      inline void to_file(std::wstring_view file_name, const JsonObject& obj)
 34      {
 35          std::wstring obj_str{ obj.Stringify().c_str() };
 36          std::ofstream{ file_name.data(), std::ios::binary } << winrt::to_string(obj_str);
 37      }
 38  
 39      inline bool has(
 40          const json::JsonObject& o,
 41          std::wstring_view name,
 42          const json::JsonValueType type = JsonValueType::Object)
 43      {
 44          return o.HasKey(name) && o.GetNamedValue(name).ValueType() == type;
 45      }
 46  
 47      template<typename T>
 48      inline std::enable_if_t<std::is_arithmetic_v<T>, JsonValue> value(const T arithmetic)
 49      {
 50          return json::JsonValue::CreateNumberValue(arithmetic);
 51      }
 52  
 53      template<typename T>
 54      inline std::enable_if_t<!std::is_arithmetic_v<T>, JsonValue> value(T s)
 55      {
 56          return json::JsonValue::CreateStringValue(s);
 57      }
 58  
 59      inline JsonValue value(const bool boolean)
 60      {
 61          return json::JsonValue::CreateBooleanValue(boolean);
 62      }
 63  
 64      inline JsonValue value(JsonObject value)
 65      {
 66          return value.as<JsonValue>();
 67      }
 68  
 69      inline JsonValue value(JsonValue value)
 70      {
 71          return value; // identity function overload for convenience
 72      }
 73  
 74      template<typename T, typename D = std::optional<T>>
 75          requires std::constructible_from<std::optional<T>, D>
 76      void get(const json::JsonObject& o, const wchar_t* name, T& destination, D default_value = std::nullopt)
 77      {
 78          try
 79          {
 80              if constexpr (std::is_same_v<T, bool>)
 81              {
 82                  destination = o.GetNamedBoolean(name);
 83              }
 84              else if constexpr (std::is_arithmetic_v<T>)
 85              {
 86                  destination = static_cast<T>(o.GetNamedNumber(name));
 87              }
 88              else if constexpr (std::is_same_v<T, std::wstring>)
 89              {
 90                  destination = o.GetNamedString(name);
 91              }
 92              else if constexpr (std::is_same_v<T, json::JsonObject>)
 93              {
 94                  destination = o.GetNamedObject(name);
 95              }
 96              else
 97              {
 98                  static_assert(std::bool_constant<std::is_same_v<T, T&>>::value, "Unsupported type");
 99              }
100          }
101          catch (...)
102          {
103              std::optional<T> maybe_default{ std::move(default_value) };
104              if (maybe_default.has_value())
105                  destination = std::move(*maybe_default);
106          }
107      }
108  
109  }