Skip to content

Support serialisation of unique_ptr<> and shared_ptr<> #975

Closed

Description

@Timmmm

If you try something like this:

std::unique_ptr<int> a = ...;
json j = a;

It will fail with a template error (get_json() isn't defined for unique_ptr). I can't see a good reason why that shouldn't work by default. I would expect null for null pointers and the actual value otherwise.

Activity

  1. gregmarr commented on Feb 16, 2018

    @gregmarr
    Contributor

    I'm just a user, but I don't think having this library supporting automatic pointer dereference is a good idea.

  2. Timmmm commented on Feb 16, 2018

    @Timmmm
    Author

    Because...

  3. nlohmann commented on Feb 17, 2018

    @nlohmann
    Owner

    I am also not sure whether such an implicit dereference under the hood is adding simplicity or rather surprise.

    In any case, the described behavior can be achieved without changing the library:

    #include "json.hpp"
    #include <iostream>
    
    using json = nlohmann::json;
    
    namespace nlohmann {
        template <typename T>
        struct adl_serializer<std::unique_ptr<T>> {
            static void to_json(json& j, const std::unique_ptr<T>& opt) {
                if (opt.get()) {
                    j = *opt;
                } else {
                    j = nullptr;
                }
            }
        };
    }
    
    int main()
    {
        std::unique_ptr<int> a = std::make_unique<int>(1);
        std::unique_ptr<int> b;
        json j = {a, b};
        
        std::cout << j << std::endl;
    }

    (prints [1,null])

  4. nlohmann commented on Feb 19, 2018

    @nlohmann
    Owner

    Can I close this issue?

  5. Timmmm commented on Feb 28, 2018

    @Timmmm
    Author

    Yep, sorry for the delay - that looks excellent. Given that it is that easy to do without changing the library I wouldn't change it either. Though maybe add it to the Readme?

  6. theodelrieu commented on Feb 28, 2018

    @theodelrieu
    Contributor

    There is already an example for boost::optional in the Readme, so I don't think adding one for unique_ptr/shared_ptr is very useful.

  7. lattice0 commented on Aug 29, 2020

    @lattice0

    Shouldn't at least std::optional be supported?

  8. nlohmann commented on Aug 29, 2020

    @nlohmann
    Owner

    For std::optional, see #2229.

  9. RAnders00 commented on Jan 9, 2024

    @RAnders00

    Because it's not been posted by anyone, here is a complete implementation that also includes from_json:

    #include "nlohmann/json.hpp"
    #include <memory>
    
    NLOHMANN_JSON_NAMESPACE_BEGIN
    
    // Allows serializing and deserializing contents behind a std::unique_ptr.
    // See also: https://github.com/nlohmann/json/issues/975
    template <typename T> struct adl_serializer<std::unique_ptr<T>> {
        template <typename BasicJsonType> static void to_json(BasicJsonType& json_value, const std::unique_ptr<T>& ptr)
        {
            if (ptr.get()) {
                json_value = *ptr;
            } else {
                json_value = nullptr;
            }
        }
    
        template <typename BasicJsonType> static void from_json(const BasicJsonType& json_value, std::unique_ptr<T>& ptr)
        {
            T inner_val = json_value.template get<T>();
            ptr = std::make_unique<T>(std::move(inner_val));
        }
    };
    
    NLOHMANN_JSON_NAMESPACE_END

    (The same approach works for std::shared_ptr with std::make_shared as well)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    solution: proposed fixa fix for the issue has been proposed and waits for confirmation

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions