#include <iostream>
#include <string>
#include <string_view>
#include <boost/pfr.hpp>
#include <nlohmann/json.hpp>
struct UV
{
    int u;
    int v;
};
struct XYZ {
    int x;
    int y;
    int z;
    UV uv;
};
// 定义一个简单的结构体用于演示
struct Person {
    std::string name;
    int age;
    double height;
    XYZ pos = { 1,2,3 };
    std::vector<std::string> dd = { "10,11","ddd"};
};

// 使用 SFINAE 约束的通用打印函数
template <typename T>
    requires std::is_aggregate_v<T>
void print_struct_members(const T& obj) {
    std::cout << "{" << std::endl;
    boost::pfr::for_each_field_with_name(obj, [&](std::string_view name, const auto& field) {

        //std::remove_cvref_t去除 const等引用返回基础类型 避免 std::decay_t 数组指针退化
        if constexpr (std::is_aggregate_v<std::remove_cvref_t<decltype(field)>>)
        {
            std::cout << "\"" << name << "\"" << ":" << std::endl;
            print_struct_members(field);
        }
        else
        {
            std::cout << "\"" << name << "\"" << ": " << field  << std::endl;
        }
        });
    std::cout << "}" << std::endl;
}


// Concept for types that nlohmann::json can serialize/deserialize directly
template<typename T>
concept JsonSerializable = requires(T t, nlohmann::json j) {
    { j = t } -> std::same_as<nlohmann::json&>;
    { j.get<T>() } -> std::same_as<T>;
};

// Concept for std::vector
template<typename T>
concept IsVector = std::same_as<T, std::vector<typename T::value_type>>;

// Concept for std::array
template<typename T>
concept IsArray = std::same_as<T, std::array<typename T::value_type, T::size()>>;

// Concept for reflectable structs
template<typename S>
concept IsReflectable = requires {
    requires std::is_aggregate_v<S>;
    requires checkStructTypes<S>(std::make_index_sequence<boost::pfr::tuple_size_v<S>>{});
    requires boost::pfr::tuple_size_v<S> > 0; // Ensure struct is not empty
};
// Concept for allowed field types
template<typename T>
concept FieldValueType = JsonSerializable<T> ||
IsReflectable<T> || (IsVector<T> &&  IsReflectable<typename T::value_type>) || (IsArray<T> &&  IsReflectable<typename T::value_type>);

// Helper to check if all fields of a struct satisfy FieldValueType
template<typename S, std::size_t... Is>
consteval bool checkStructTypes(std::index_sequence<Is...>) noexcept {
    return (FieldValueType<std::remove_cvref_t<decltype(boost::pfr::get<Is>(std::declval<S&>()))>> && ...);
}

// Static assert to improve error messages
template<typename T>
    requires IsReflectable<T>
struct JsonSer {
    static_assert(IsReflectable<T>, "Type T must be an aggregate struct with fields satisfying FieldValueType");

public:
    using JsonType = nlohmann::json;

    // Serialization: Convert struct to JSON
    static JsonType toJson(T const& object) {
        JsonType json;
        boost::pfr::for_each_field_with_name(object, [&json](std::string_view const name, auto const& field) {
            try {
                using ChildType = std::remove_cvref_t<decltype(field)>;
                if constexpr (IsReflectable<ChildType>) {
                    json[name] = JsonSer<ChildType>::toJson(field);
                }
                else if constexpr (IsVector<ChildType> || IsArray<ChildType>) {
                    JsonType array = JsonType::array();
                    for (const auto& element : field) {
                        if constexpr (IsReflectable<typename ChildType::value_type>) {
                            array.push_back(JsonSer<typename ChildType::value_type>::toJson(element));
                        }
                        else {
                            array.push_back(element);
                        }
                    }
                    json[name] = array;
                }
                else {
                    static_assert(JsonSerializable<ChildType>, "Field type must be JSON-serializable");
                    json[name] = field;
                }
            }
            catch (const std::exception& e) {
                std::cerr << "Serialization error for field " << name << ": " << e.what() << "\n";
            }
            });
        return json;
    }

        static T fromJson(const std::string& json) {
        return fromJson(JsonType::parse(json));
    }

    // Deserialization: Convert JSON to struct
    static T fromJson(const JsonType& json) {
        std::cout << "Input JSON:\n" << json.dump(2) << "\n";
        T object{};
        boost::pfr::for_each_field_with_name(object, [&json](std::string_view const name, auto& field) {
            std::cout << "Checking key: " << name << "\n";
            try {
                using ChildType = std::remove_cvref_t<decltype(field)>;
                if (json.contains(name)) {
                    std::cout << "Found key: " << name << "\n";
                    if constexpr (IsReflectable<ChildType>) {
                        field = JsonSer<ChildType>::fromJson(json[name]);
                    }
                    else if constexpr (IsVector<ChildType>) {
                        if (json[name].is_array()) {
                            field.clear();
                            for (const auto& item : json[name]) {
                                if constexpr (IsReflectable<typename ChildType::value_type>) {
                                    field.push_back(JsonSer<typename ChildType::value_type>::fromJson(item));
                                }
                                else {
                                    static_assert(JsonSerializable<typename ChildType::value_type>, "Vector element type must be JSON-serializable");
                                    field.push_back(item.get<typename ChildType::value_type>());
                                }
                            }
                        }
                        else {
                            std::cerr << "Field " << name << " is not an array\n";
                        }
                    }
                    else if constexpr (IsArray<ChildType>) {
                        if (json[name].is_array() && json[name].size() <= field.size()) {
                            std::size_t i = 0;
                            for (const auto& item : json[name]) {
                                if constexpr (IsReflectable<typename ChildType::value_type>) {
                                    field[i] = JsonSer<typename ChildType::value_type>::fromJson(item);
                                }
                                else {
                                    static_assert(JsonSerializable<typename ChildType::value_type>, "Array element type must be JSON-serializable");
                                    field[i] = item.get<typename ChildType::value_type>();
                                }
                                ++i;
                            }
                        }
                        else {
                            std::cerr << "Field " << name << " is not an array or size mismatch\n";
                        }
                    }
                    else {
                        static_assert(JsonSerializable<ChildType>, "Field type must be JSON-serializable");
                        field = json[name].get<ChildType>();
                    }
                }
                else {
                    std::cerr << "Key not found: " << name << "\n";
                }
            }
            catch (const std::exception& e) {
                std::cerr << "Deserialization error for field " << name << ": " << e.what() << "\n";
            }
            });
        return object;
    }
};

//int test_print_struct() {
int main(){
    Person p{ "Alice", 30, 1.75 };
  
    try {
        auto result_json = JsonSer<Person>::toJson(p).dump(4);
        std::cout << result_json << std::endl;
        Person ccc = JsonSer<Person>::fromJson(result_json);
        std::cout << ccc.name << std::endl;
    }
    catch (std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
   

    return 0;
}

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐