Skip to content

basic_json templated on a "policy" class #456

@jaredgrubb

Description

@jaredgrubb

I'm enjoying the library, however I have a couple comments:

  • the mangled name is really awful:
    nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::adl_serializer>
  • it's not possible to extend basic_json beyond the types

The mangled name is cosmetic, but it is annoying to have to try to read stackshots or prints in debuggers.

One idea I had was to refactor basic_json to be based on a policy type, aka nlohmann::basic_json<nlohmann::default_policy>, where default_policy would be defined something like:

template <
    template<typename U, typename V, typename... Args> class ObjectType = std::map,
    template<typename U, typename... Args> class ArrayType = std::vector,
    class StringType = std::string,
    class BooleanType = bool,
    class NumberIntegerType = std::int64_t,
    class NumberUnsignedType = std::uint64_t,
    class NumberFloatType = double,
    template<typename U> class AllocatorType = std::allocator,
    template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer
    >
struct policy_base {
    using object_t = ...;
    using array_t = ...;
    // ...

    using json_value = ... /* union definition */;
    using parser = ...;

    // ... whatever accessors are needed to complete the abstraction
};

struct default_policy : policy_base<> {};

It would take a bit of work to get basic_json refactored in terms of the policy, and to figure out exactly what should go in each part. But I think this could make the design a bit cleaner in that it turns basic_json into the interface-glue that makes the type easy to use, and the policy object becomes the low-level details that provide a nice customization point.

The kinds of customizations that this could enable:

  • allow the union to be extended to support user types (for example, std::shared_ptr<json>, or std::unique_ptr<LazyJsonLoader> that only deserializes a sub-object if it gets used, or to allow EmployeeRecord to be placed directly in the union and serialized inline, but also provide conversion-operators like other types)
  • maybe the parser could be extended to support non-conforming extensions (like trailing comma); I support that this library doesnt support this out of the box, but it would be nice if it was doable without too much work. (I have not looked at the parser, so maybe this is not even remotely possible right now).

Anyway, I just wanted to throw the idea out there to get feedback.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind: enhancement/improvementstate: please discussplease discuss the issue or vote for your favorite optionstate: stalethe issue has not been updated in a while and will be closed automatically soon unless it is updated

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions