open-source-parsers / open-source-parsers/jsoncpp
Serialization
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 8.9k
- Forks
- 2.7k
- Avg merge
- 31m
- Merged PRs (30d)
- 1
Description
Hello, it's the first time I create an issue under an opensource.
We use jsoncpp 0.5.0 version as a third lib. Recently I realize json to struct function base on jsoncpp's Json::Value.
Here is my serializer.h.
namespace Json {
template <typename T, T... S, typename F>
constexpr void for_sequence(std::integer_sequence<T, S...>, F&& f) {
using unpack_t = int[];
(void)unpack_t{(static_cast<void>(f(std::integral_constant<T, S>{})), 0)..., 0};
}
template<typename Class, typename T>
struct PropertyImpl {
constexpr PropertyImpl(T Class::*aMember, const char* aName) : member{aMember}, name{aName} {}
using Type = T;
T Class::*member;
const char* name;
};
template<typename Class, typename T>
constexpr auto property(T Class::*member, const char* name) {
return PropertyImpl<Class, T>{member, name};
}
template<typename T>
struct PropertyTag {
typedef char yes;
typedef long no;
template <typename TT>
static auto CheckTag(int) -> decltype(std::declval<TT>().properties, yes());
template <typename TT>
static std::false_type CheckTag(...);
static constexpr bool hasProperty = std::is_same<decltype(CheckTag<T>(0)), yes>::value;
};
template<typename T, typename std::enable_if<PropertyTag<T>::hasProperty, int>::type = 0>
T FromJson(const Json::Value& value);
template<typename T, typename std::enable_if<!PropertyTag<T>::hasProperty, int>::type = 0>
T FromJson(const Json::Value& value) {
return T();
}
template<typename T, typename std::enable_if<PropertyTag<T>::hasProperty, int>::type = 0>
Json::Value ToJson(const T &object);
template<typename T, typename std::enable_if<!PropertyTag<T>::hasProperty, int>::type = 0>
Json::Value ToJson(const T &object) {
return Json::Value();
}
template<typename T, typename std::enable_if<PropertyTag<T>::hasProperty, int>::type = 0>
inline T asAny(const Json::Value& value) {
return FromJson<T>(value);
}
template <typename T, typename std::enable_if<!PropertyTag<T>::hasProperty, int>::type = 0>
inline T asAny(const Json::Value& value) {
return T{};
}
template<>
inline int asAny<int>(const Json::Value& value) {
return value.asInt();
}
template<>
inline std::string asAny<std::string>(const Json::Value& value) {
return value.asString();
}
template<>
inline char* asAny<char*>(const Json::Value& value) {
if (value.type() != Json::stringValue) {
return "";
}
return const_cast<char*>(value.asCString());
}
template<>
inline bool asAny<bool>(const Json::Value& value) {
return value.asBool();
}
template<>
inline double asAny<double>(const Json::Value& value) {
return value.asDouble();
}
template<>
inline float asAny<float>(const Json::Value& value) {
return value.asDouble();
}
template<>
inline uint asAny<uint>(const Json::Value& value) {
return value.asUInt();
}
template<>
inline std::vector<std::string> asAny<std::vector<std::string>>(const Json::Value& value) {
std::vector<std::string> vec;
if (value.isArray() && value.size() != 0) {
for (uint i = 0; i < value.size(); ++i) {
vec.push_back(value[i].asString());
}
}
return vec;
}
template<>
inline std::vector<int> asAny<std::vector<int>>(const Json::Value& value) {
std::vector<int> vec;
if (value.isArray() && value.size() != 0) {
for (uint i = 0; i < value.size(); ++i) {
vec.push_back(value[i].asInt());
}
}
return vec;
}
template <typename T, typename std::enable_if<PropertyTag<T>::hasProperty, int>::type = 0>
Json::Value convertJson(const T& object) {
return ToJson(object);
}
template <typename T, typename std::enable_if<!PropertyTag<T>::hasProperty, int>::type = 0>
Json::Value convertJson(const T &object) {
return Json::Value();
}
template<>
Json::Value convertJson<int>(const int& object) {
return Json::Value(object);
}
template<>
Json::Value convertJson<uint>(const uint& object) {
return Json::Value(object);
}
template<>
Json::Value convertJson<float>(const float& object) {
return Json::Value(object);
}
template<>
Json::Value convertJson<double>(const double& object) {
return Json::Value(object);
}
template<>
Json::Value convertJson<std::string>(const std::string& object) {
return Json::Value(object);
}
template<>
Json::Value convertJson<char*>(char* const& object) {
if (object == nullptr) {
return Json::Value("");
}
return Json::Value(object);
}
template<>
Json::Value convertJson<std::vector<std::string>>(const std::vector<std::string>& object) {
Json::Value data;
for (auto str : object) {
data.append(str);
}
return data;
}
template<>
Json::Value convertJson<std::vector<int>>(const std::vector<int>& object) {
Json::Value data;
for (auto str : object) {
data.append(str);
}
return data;
}
template<typename T, typename std::enable_if<PropertyTag<T>::hasProperty, int>::type>
T FromJson(const Json::Value& data) {
T object;
constexpr auto nbProperties = std::tuple_size<decltype(T::properties)>::value;
for_sequence(std::make_index_sequence<nbProperties>{}, [&](auto i){
constexpr auto property = std::get<i>(T::properties);
using Type = typename decltype(property)::Type;
if (data.isMember(property.name)) {
object.*(property.member) = std::move(asAny<Type>(data[property.name]));
}
});
return object;
}
template<typename T, typename std::enable_if<PropertyTag<T>::hasProperty, int>::type>
Json::Value ToJson(const T& object) {
Json::Value data;
constexpr auto nbProperties = std::tuple_size<decltype(T::properties)>::value;
for_sequence(std::make_index_sequence<nbProperties>{}, [&](auto i){
constexpr auto property = std::get<i>(T::properties);
using Type = typename decltype(property)::Type;
data[property.name] = std::move(convertJson<Type>(object.*(property.member)));
});
return data;
}
}
it bases on c++14.
I provide Json::ToJson() and Json::FromJson() two interface for serialization and deserialization.
But It just support some basic type, std::vector<std::string>, std::vector<int>, and customized struct or class.
for example, InnerS2 has tuple type member named properties. It can be serialized.
struct InnerS2 {
std::string m1;
constexpr static auto properties = std::make_tuple(
Json::property(&InnerS2::m1, "m1")
);
};
What about your ideas ?
I will seriously refer to your suggestions. thx.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue supplies serializer.h and an InnerS2 example, but names no repository file or test. Review the proposed Json::ToJson and Json::FromJson interfaces against jsoncpp's Json::Value API, then define a concrete supported-type scope and acceptance tests before implementation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100