json icon indicating copy to clipboard operation
json copied to clipboard

General map-like conversions

Open vinniefalco opened this issue 5 years ago • 5 comments

To repeat what I said on Slack, now that tuple-likes are supported it looks like general maps (where the key is not string-like) would also start working (being treated as sequences of pairs.) If they do work, we need to have a test for it. If they don't, we might want to look into why.

vinniefalco avatar Mar 04 '21 02:03 vinniefalco

I tested and it does indeed work. For example:

enum class K { A, B, C };

// tag_invoke for K removed for brevity

check(std::map<K, int> {
    { K::A, 1 }, { K::B, 2}, { K::C, 3},
});

I have to comment that serializing maps into arrays is suboptimal. If we could check during compilation that tag_invoke for key produces a json::string then we would be able to serialize them into objects. But that would require a different tag_invoke signature. Something like json::value tag_invoke(value_from_tag, K const&) ( and users could write json::string tag_invoke(value_from_tag, K const&)).

grisumbras avatar Mar 04 '21 06:03 grisumbras

So, since #515 we do support all associative containers. Currently

  • If the container has unique keys (checked via the result type of emplace) and the type of key is StringLike, we convert to/from object
  • Otherwise we convert to/from array of 2-element arrays.

Should we pursue the former to expand to maps with keys that convert to/from json::string? E.g.

enum class E { e1, e2, e3 };
void tag_invoke(json::value_from_tag, json::value& jv, E e);

std::map<E, X> my_map;
auto jv = value_from(my_map);

grisumbras avatar May 23 '21 06:05 grisumbras

I don't know

vinniefalco avatar May 26 '21 15:05 vinniefalco

If #989 is done, this could be supported. E.g.:

enum class E { e1, e2, e3 };
struct E_String { // is_string_like
  E e;
  E_String(E);
  explicit E_String(string_view);
  operator string_view() const;
};
 
namespace boost::json {
template<>
struct serialize_as<E> : mp11::identity<E_String> {};
}

std::map<E, X> my_map;
auto jv = value_from(my_map);

grisumbras avatar Apr 08 '24 16:04 grisumbras

let someone ask for it :)

vinniefalco avatar Apr 09 '24 19:04 vinniefalco