Skip to content
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

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

Closed
Timmmm opened this issue Feb 16, 2018 · 9 comments
Closed

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

Timmmm opened this issue Feb 16, 2018 · 9 comments
Labels
solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@Timmmm
Copy link

Timmmm commented Feb 16, 2018

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.

@gregmarr
Copy link
Contributor

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

@Timmmm
Copy link
Author

Timmmm commented Feb 16, 2018

Because...

@nlohmann
Copy link
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])

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Feb 17, 2018
@nlohmann
Copy link
Owner

Can I close this issue?

@Timmmm
Copy link
Author

Timmmm commented Feb 28, 2018

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?

@theodelrieu
Copy link
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.

@lattice0
Copy link

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

@nlohmann
Copy link
Owner

For std::optional, see #2229.

@RAnders00
Copy link

RAnders00 commented Jan 9, 2024

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
Labels
solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

6 participants