Skip to content

Latest commit

 

History

History
97 lines (73 loc) · 2.46 KB

unknown-keys.md

File metadata and controls

97 lines (73 loc) · 2.46 KB

Unknown Keys

Sometimes you don't know in advance all the keys of your objects. By default, glaze will error on unknown keys. If you set the compile time option error_on_unknown_keys = false, the behavior will change to skip the unknown keys.

Furthermore it is possible to customize the handling of object unknown keys at read and/or write time by defining unknown_read and unknown_write members of meta class as pointer to member or pointer to method.

Note : unknown_write is using glz::merge internally so unknown keys will be written at the end of object.

Example

struct my_struct
{
  std::string hello;
  std::string zzz;
  std::map<glz::sv, glz::raw_json> extra; // store key/raw_json in extra map

  // with methods
  // void my_unknown_read(const glz::sv& key, const glz::raw_json& value) { 
  //     extra[key] = value;
  // };
  // std::map<glz::sv, glz::raw_json> my_unknown_write() const {
  //    return extra;
  // }

};

template <>
struct glz::meta<my_struct> {
   using T = my_struct;
   static constexpr auto value = object(
      "hello", &T::hello,
      "zzz", &T::zzz
   );
   
   // with members
   static constexpr auto unknown_write{&T::extra};
   static constexpr auto unknown_read{&T::extra};
   // with methods
   // static constexpr auto unknown_write{&T::my_unknown_write};
   // static constexpr auto unknown_read{&T::my_unknown_read};

};

// usage
std::string buffer = R"({"hello":"Hello World!","lang":"en","zzz":"zzz"})";
my_struct s{};

// decodes and retains extra unknown fields (lang) in extra map
glz::context ctx{};
glz::read<glz::opts{.error_on_unknown_keys = false}>(s, buffer, ctx);

// update
s.hello = "Hi !"

// encodes output string
std::string out{};
glz::write_json(s, out);

// out ==  {"hello":"Hi !","zzz":"zzz","lang":"en"}

Example 2 : Known extra type

If the type of extra keys is known, this would work

struct my_struct
{
  std::string infinite;
  int zero;
  std::map<glz::sv, int> numbers;
};

template <>
struct glz::meta<my_struct> {
   using T = my_struct;
   static constexpr auto value = object(
      "infinite", &T::infinite,
      "zero", &T::zero
   );
   
   static constexpr auto unknown_read{&T::extra};
};

// usage
// note extra keys (one, two) are of type int
std::string buffer = R"({"inf":"infinite","zero":0,"one":1,"two":2})";
my_struct s{};

// decodes and retains extra unknown fields (lang) in extra map
glz::context ctx{};
glz::read<glz::opts{.error_on_unknown_keys = false}>(s, buffer, ctx);