Skip to content

Add std::shared_ptr support #190

@Hippid

Description

@Hippid

Hi,
Thank you for this awesome project.
I chose your json library since I'm using a few classes that use std::shared_ptr and your library had some examples of how to use it.

Anyway I wanted to do something like this:
(see IModel.h below for implementation details)

JSONCONS_STRICT_MEMBER_TRAITS_DECL(std::shared_ptr<mynamespace::Model>, path, x, y, z)
JSONCONS_STRICT_MEMBER_TRAITS_DECL(std::shared_ptr<mynamespace::IModels>, Models)

Unfortunately this did not work and implementing it like the examples do would cause a bunch of repetitive code.

To solve this problem I made macro and was wondering if you could add it to the jsoncons project and examples.


#define JSONCONS_ADD_SHARED_PTR_MEMBER(ValueType, ...)  \
JSONCONS_STRICT_MEMBER_TRAITS_DECL(ValueType, __VA_ARGS__) \
namespace jsoncons { \
	template<class Json> \
	struct json_type_traits<Json, std::shared_ptr<ValueType>> { \
		static bool is(const Json& j, const ValueType& v) noexcept { \
			return j.is<ValueType>(); \
		} \
\
		static std::shared_ptr<ValueType> as(const Json& j) { \
			return std::make_shared<ValueType>(j.as<ValueType>()); \
		} \
\
		static Json to_json(const std::shared_ptr<ValueType>& ptr) { \
			if (ValueType* p = dynamic_cast<ValueType*>(ptr.get())) { \
				Json j(*p); \
				return j; \
			} else { \
				throw std::runtime_error("Not " + typeid(ValueType).name); \
			} \
		} \
	}; \
} \

Note: It internally uses the JSONCONS_STRICT_MEMBER_TRAITS_DECL macro and simply adds a bit of wrapper code to support the 'std::shared_ptr' method variant.
Therefore the 'normal' variant (that does not use std::shared_ptr) is also supported with this macro.
Since it uses the existing macro it works out of the box with features like std::vector.

Anyway the usage is now short and clean :)

JSONCONS_ADD_SHARED_PTR_MEMBER(mynamespace::IModel, path, x, y, z)
JSONCONS_ADD_SHARED_PTR_MEMBER(mynamespace::IModels, Models)
std::shared_ptr<IModels> jsonMethod(std::string inputJsonFile = "input.json) {
    std::ifstream is(inputJsonFile);
    json j = json::parse(is);
    return j.as<std::shared_ptr<IModels>>();
}

IModel.h

#include <vector>
#include <string>

namespace mynamespace {
	class IModel {
	public:
            inline IModel() {
                path = "";
                x = 0;
                y = 0;
                z = 0;
            };

            inline IModel(std::string _path, int _x, int _y, int _z) {
                path = _path;
                x = _x;
                y = _y;
                z = _z;
            };
        
            std::string path;
            int x;
            int y;
            int z;            
	};
	
	class IModels {	
	public:
            inline IModels() {
            };
            std::vector<std::shared_ptr<IModel>> Models;
    };
}

Regards,

Twan Springeling

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions