在json反序列化的运行时模板函数类型转换

时间:2015-12-24 00:37:51

标签: c++11 casting json-deserialization template-function folly

我想编写一个函数,将数组的json表示反序列化为std :: vector。我正在使用的json库是Facebook愚蠢的库的一部分。我想实现如下的一些事情,但遗憾的是它不起作用:

template<typename T>
static bool deserializeHelper(std::string fieldName, vector< T >& structField, const folly::dynamic& jsonObj) {        
    if(auto* jsonField = jsonObj.get_ptr(fieldName)){
        if(jsonField->isArray()) {
           for(auto& elem : *jsonField) {
               if(elem.isInt()) {
                   structField.push_back(elem.asInt());
               } else if(elem.isString()){
                   structField.push_back(elem.asString());
               } else if(elem.isDouble()) {
                   structField.push_back(elem.asDouble());
               } else if(elem.isBool()) {
                   structField.push_back(elem.asBool());
               } else return false;
           }
        } else return false;
    }

    return true;
}

在上面的代码中,jsonField是数组字段的表示。所以代码只是尝试遍历数组;然后为每个元素;它将尝试推回到通用矢量:矢量。问题是代码无法编译,因为它会抱怨它无法从std :: string转换为int;当T = int;

我不知道如何在不需要实现4方法重载函数的情况下编写类似的泛型函数。 static bool deserializeHelper(std :: string fieldName,vector&lt; int&gt;&amp; structField,const folly :: dynamic&amp; jsonObj)....

感谢。

2 个答案:

答案 0 :(得分:0)

似乎代码如下所示。我只是想知道是否有任何瓶颈,开销或以下工作正常:

template<typename T>
static bool deserializeHelper(std::string fieldName, vector<T>& structField, const folly::dynamic& jsonObj) {
    if(auto* jsonField = jsonObj.get_ptr(fieldName)){
        if(jsonField->isArray()) {
            for(auto& elem : *jsonField) {
                if(elem.isInt()) {
                    int tmp = elem.getInt();
                    structField.push_back(*(static_cast<T*>(static_cast<void*>(&tmp))));
                } else if(elem.isString()){
                    std::string tmp = elem.getString().toStdString();
                    structField.push_back(*(static_cast<T*>(static_cast<void*>(&tmp))));
                } else if(elem.isDouble()) {
                    double tmp = elem.getDouble();
                    structField.push_back(*(static_cast<T*>(static_cast<void*>(&tmp))));
                } else if(elem.isBool()) {
                    bool tmp = elem.getBool();
                    structField.push_back(*(static_cast<T*>(static_cast<void*>(&tmp))));
                } else return false;
            }
        } else return false;
    }

    return true;
}

基本上,在从void *到T *进行另一次转换之前,它会首先尝试转换为void *。我想知道是否有什么可以改进。

感谢。

答案 1 :(得分:0)

这两种类型安全的方法是:

  • 写下你已经拒绝的4种方法;和
  • T语句中测试if

看起来像这样:

#include <type_traits>

template<typename T>
static bool deserializeHelper(std::string fieldName, vector< T >& structField, const folly::dynamic& jsonObj) {        
    if(auto* jsonField = jsonObj.get_ptr(fieldName)){
        if(jsonField->isArray()) {
           for(auto& elem : *jsonField) {
               if(std::is_same<T, bool>::value) {
                   structField.push_back(elem.asBool());
               } else if(std::is_convertible<int64_t, T>::value) {
                   structField.push_back(elem.asInt());
               } else if(std::is_convertible<std::string, T>::value){
                   structField.push_back(elem.asString());
               } else if(std::is_convertible<double, T>::value) {
                   structField.push_back(elem.asDouble());
               } else return false;
           }
        } else return false;
    }
    return true;
}

所有这些if都将被静态评估,因此编译后的代码与只有used-branch一样有效。