-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Maps with enum class keys which are convertible to JSON strings should be converted to JSON dictionaries #1217
Comments
I'll take a look at it tomorrow |
As information: In this example, there is "only" a Species -> |
I see problems when there are enum values that are json-ized into non-strings:
|
@RokerHRO Indeed, what can be done is the following: If the map/unordered_map/etc... This becomes quite confusing, but I think it still makes sense. |
@theodelrieu : so what shall be done when a map contains both?
some keys are convertible to strings, others are not. So this map would become a JSON object when all keys are (convertible to) strings, and when at least one element's key is not convertible to string the whole thing is JSON-ized as array-of-pairs? I'd say, that would be very confusing! Please, don't do that! So I hope I have misunderstand you. ;-) |
I agree this is quite terrible, and even if having such hybrid representation of the same type looks bad in the first place, there is no way to enforce that every enum value is converted to a string at compile time. Therefore I think you should instead partially specialize namespace nlohmann {
template <typename T>
struct adl_serializer<std::map<Species, T>> {
using Map = std::map<Species, T>;
static void from_json(json const& j, Map& m) { /* ... */ }
static void to_json(json& j, Map const& m) { /* ... */ }
};
} |
OK, OK :) Generating such JSON would indeed be quite confusing. But could we have the parser be able to deserialise the input Partially specialising |
PS. When serialising std::unordered_map into an array, what determines the ordering of entries? |
@katastrofa999
Same problem here, how can we enforce that at compile-time? The only thing there is here is the
Not necessarily: namespace nlohmann {
template <typename T, typename = std::enable_if_t<is_enum_class<T>::value>>
struct adl_serializer<...> { /* Same code as above */ };
} The |
@katastrofa999
We iterate on the object with |
I meant something like that:
I mean, you can't generally enforce the success of deserialisation at compile time, because it depends on inputs which you know only at runtime...
That's not terribly great for |
@katastrofa999: I don't like that if the conversion is not roundtrip-safe. So your JSON object |
Could this be optional behaviour, then? If one uses JSON files to store user-editable application configuration, then writing maps by hand as JSON objects is more intuitive than writing them as JSON arrays. Usually, you're not going to change the configuration after loading it from JSON, or serialise it back to JSON. If this behaviour is optional, you can add a check that the serialisation fails at runtime if the map cannot be serialised as JSON object, without affecting the rest of the code which does not use this option. |
Sorry for the confusion, I mean that the library performs a list of compile-time checks to decide which overload it has to use (e.g. if In this specific case, your enum is not convertible to string (i.e. std::is_convertible returns false).
I agree, but it's related to using unordered containers in the first place, I don't see how the library could guess the correct order when serializing those. |
Introducing specific cases in the default-provided conversions is tricky, I'd like to avoid such complexity in the library's code (which is already quite complex...). For those specific cases, I'd recommand the solution proposed above, with partial specializations. It will not harm other users of the library, and will fulfill your use-case (even if it can be painful to implement, but we can help you having a robust implementation). |
Thanks, I'll take a look at that. |
The following code:
produces the output
[["DOG",false],["OCTOPUS",true]]
, which is not what the user would expect IMHO. Would it be possible to render this map as{"DOG":false,"OCTOPUS":true}
?The text was updated successfully, but these errors were encountered: