nlohmann/json支持QString、QVector、QMap

代码


#include <QString>
#include <QVector>
#include <QMap>
NLOHMANN_JSON_NAMESPACE_BEGIN
template <>
struct adl_serializer<QString> {
	static void to_json(json& j, const QString& opt) {
        j = opt.toStdString();
	}

	static void from_json(const json& j, QString& opt) {
        opt = QString::fromStdString(j.template get<std::string>());
	}
};

template <typename T>
struct adl_serializer<QVector<T>> {
	static void to_json(json& j, const QVector<T>& opt) {
#if QT_DEPRECATED_SINCE(5, 14) && QT_VERSION < QT_VERSION_CHECK(6,0,0)
        j = std::vector<T>(opt.begin(), opt.end());
#else
        j = opt.toStdVector();
#endif
	}

	static void from_json(const json& j, QVector<T>& opt) {
#if QT_DEPRECATED_SINCE(5, 14) && QT_VERSION < QT_VERSION_CHECK(6,0,0)
        const auto& _vector = j.template get<std::vector<T>>();
        opt = QVector<T>(_vector.cbegin(), _vector.cend());
#else
        opt = QVector<T>::fromStdVector(j.template get<std::vector<T>>());
#endif
	}
};

template <typename Key,typename T>
struct adl_serializer<QMap<Key,T>> {
	static void to_json(json& j, const QMap<Key, T>& opt) {
        j = opt.toStdMap();
	}

	static void from_json(const json& j, QMap<Key, T> &opt) {
        opt = QMap<Key, T>(j.template get<std::map<Key, T>>());
	}
};

NLOHMANN_JSON_NAMESPACE_END

  1. 加在json.hpp要注意在唯一定义之间
#ifndef INCLUDE_NLOHMANN_JSON_HPP_
#define INCLUDE_NLOHMANN_JSON_HPP_
.....

#endif  // INCLUDE_NLOHMANN_JSON_HPP_
  1. 加在外侧

原理

官方原文

Arbitrary Type Conversions任意类型转换

How do I convert third-party types?

如何转换第三方类型?

This requires a bit more advanced technique. But first, let’s see how this conversion mechanism works:

这需要更先进的技术。但首先,让我们看看这个转换机制是如何工作的:

The library uses JSON Serializers to convert types to json. The default serializer for nlohmann::json is nlohmann::adl_serializer (ADL means Argument-Dependent Lookup).

该库使用JSON序列化器将类型转换为json。nlohmann::json的默认序列化器是nlohmann::adl_serializer(ADL表示参数依赖的序列化器(实参依赖查找)。

It is implemented like this (simplified):
它是这样实现的(简化的):

template <typename T>
struct adl_serializer {
    static void to_json(json& j, const T& value) {
        // calls the "to_json" method in T's namespace
    }

    static void from_json(const json& j, T& value) {
        // same thing, but with the "from_json" method
    }
};

This serializer works fine when you have control over the type’s namespace. However, what about boost::optional or std::filesystem::path (C++17)? Hijacking the boost namespace is pretty bad, and it’s illegal to add something other than template specializations to std…

当您可以控制类型的命名空间时,此序列化程序可以正常工作。但是,boost::optionalstd::filesystem::path(C++17)呢?劫持boost命名空间是非常糟糕的,并且向std添加除了模板专门化之外的东西是非法的。

To solve this, you need to add a specialization of adl_serializer to the nlohmann namespace, here’s an example:
为了解决这个问题,你需要将adl_serializer的特殊化添加到nlohmann命名空间,这里有一个例子:

// partial specialization (full specialization works too)
// 部分专业化(完全专业化也可以)
NLOHMANN_JSON_NAMESPACE_BEGIN
template <typename T>
struct adl_serializer<boost::optional<T>> {
    static void to_json(json& j, const boost::optional<T>& opt) {
        if (opt == boost::none) {
            j = nullptr;
        } else {
            j = *opt; // this will call adl_serializer<T>::to_json which will
                      // find the free function to_json in T's namespace!
        }
    }

    static void from_json(const json& j, boost::optional<T>& opt) {
        if (j.is_null()) {
            opt = boost::none;
        } else {
            opt = j.template get<T>(); // same as above, but with
                              // adl_serializer<T>::from_json
        }
    }
};
NLOHMANN_JSON_NAMESPACE_END
  • ABI compatibility ABI兼容性
    Use NLOHMANN_JSON_NAMESPACE_BEGIN and NLOHMANN_JSON_NAMESPACE_END instead of namespace nlohmann { } in code which may be linked with different versions of this library.
    在可能与该库的不同版本链接的代码中使用NLOHMANN_JSON_NAMESPACE_BEGINNLOHMANN_JSON_NAMESPACE_END而不是命名空间namespace nlohmann{}

How can I use get() for non-default constructible/non-copyable types?

如何将get()用于非默认的可构造/不可复制类型?

There is a way, if your type is MoveConstructible. You will need to specialize the adl_serializer as well, but with a special from_json overload:
如果你的类型是 C++ 具名要求:可移动构造 (MoveConstructible),有一种方法。你还需要专门化adl_serializer,但是要使用一个特殊的from_json重载:

struct move_only_type {
    move_only_type() = delete;
    move_only_type(int ii): i(ii) {}
    move_only_type(const move_only_type&) = delete;
    move_only_type(move_only_type&&) = default;

    int i;
};

namespace nlohmann {
    template <>
    struct adl_serializer<move_only_type> {
        // note: the return type is no longer 'void', and the method only takes
        // one argument
        /*注意:返回类型不再是'void',方法只接受一个参数*/
        static move_only_type from_json(const json& j) {
            return {j.template get<int>()};
        }

        // Here's the catch! You must provide a to_json method! Otherwise, you
        // will not be able to convert move_only_type to json, since you fully
        // specialized adl_serializer on that type
        /*这是陷阱!你必须提供一个to_json方法!否则你将无法将move_only_type转换为json,
        因为您完全该类型的专用adl_serializer*/
        static void to_json(json& j, move_only_type t) {
            j = t.i;
        }
    };
}

原文图

1
2
3
4
5
6
7
8
9
10
11
12
13

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值