getml / reflect-cpp

A C++20 library for fast serialization, deserialization and validation using reflection. Supports JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML / msgpack.org[C++20]
https://getml.github.io/reflect-cpp/
MIT License
982 stars 85 forks source link

"Field name not found" even with a default value #122

Closed pupbrained closed 3 months ago

pupbrained commented 3 months ago

I'm trying to use reflect-cpp to serialize and deserialize my configuration values, but I want to give every value a default so the program can still run without a configuration (or an incomplete one). I have the configuration split into structs:

using Location = std::variant<std::string, Coords>;

struct General {
  std::string name = getenv("USER");
};

struct NowPlaying {
  std::optional<bool> enabled = false;
};

struct Weather {
  Location    location;
  std::string api_key;
  std::string units;

  fn getWeatherInfo() const -> WeatherOutput;
};

struct Config {
  General    general     = General();
  NowPlaying now_playing = NowPlaying();
  Weather    weather     = Weather();

  static fn getInstance() -> const Config&;
};

I've been testing with the General part of the config. Even though I'm supplying defaults it still complains that the fields aren't found. Is there something I'm missing or is this intended behavior? I'm not sure what else to try.

liuzicheng1987 commented 3 months ago

@pupbrained , it doesn’t quite work that way. You need to use std::optional:

https://github.com/getml/reflect-cpp/blob/main/docs/optional_fields.md

Then, you can retrieve the values using something like config.general.value_or(General())

pupbrained commented 3 months ago

@pupbrained , it doesn’t quite work that way. You need to use std::optional:

https://github.com/getml/reflect-cpp/blob/main/docs/optional_fields.md

Then, you can retrieve the values using something like config.general.value_or(General())

I see, I was mostly trying to avoid optionals (to avoid needing multiple value_or's) but if that's necessary that's fine. Thanks for the quick response.

liuzicheng1987 commented 3 months ago

@pupbrained , you can always abstract away the value_or's by using getters:

General get_general() const { return general.value_or(General()); }

I will think about this issue, but you would have to figure out whether a field has a default value at compile time. That's fairly tricky.