javascript代码实例教程-json 对c++类的序列化(自动生成代码)

发布时间:2019-01-27 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了javascript代码实例教程-json 对c++类的序列化(自动生成代码)脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。 动机】

      之前写网络协议的时候,使用的是GOOGLE PRotobuf,protobuf不但在性能和扩展性上有很好的优势,protoc自动生成c++类代码的工具,这点确实给程序员带来了很多便利。

 

做后面一项目使用的json格式来传输,然后就萌生了实现像protoc这样的工具,根据json文件来生成c++类代码,并且生成序列化代码,这样在写网络的时候就无需把jsonvalue序列化散落在各处。

 

【思路】

     之前写object-c的时候,如果你要对类的序列化,你必须实现NSCoding协议(接口), 这样的实现方式很友好,同样,我的方式则是参考NSCoding的,

 

【Code】

 

   我这里借鉴网友的一个json序列化实现方式,感觉这种方式很方便,他是通过模板来实现对内置类型的识别,而且对所有的类型都使用了统一接口:

 

 

 

 

复制代码

/*

 * Copyright (c) 2011-2012 PromIT Roy

 * 

 * PErmission is hereby granted, free of ch@R_406_2604@e, to any person oBTaining a copy

 * of this Software and associated documentation files (the "Software"), to deal

 * in the Software without restriction, including without limitation the rights

 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

 * copies of the Software, and to permit persons to whom the Software is

 * furnished to do so, subject to the following conditions:

 * 

 * The above copyright notice and this permission notice shall be included in

 * all copies or substantial portions of the Software.

 * 

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPress OR

 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DamAGES OR OTHER

 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING From,

 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

 * THE SOFTWARE.

 */

//////////////////////////////////////////////////////////////

//          From: https://ventspace.wordpress.COM/2012/10/08/c-json-serialization/

//      FileName: json_serializer_helper.hpp

//        ;modify: Sachin

//          Date: 2013/9/22 13:41

//   Description: 

//

// History:

//      <author>    <time>        <descript>

//     Sachin    2013/9/22      add

//////////////////////////////////////////////////////////////

 

#ifndef JSON_SERIALIZER_HELPER_HPP

#define JSON_SERIALIZER_HELPER_HPP

#include <lib_json/json_lib.h>

#include <boost/utility.hpp>

#include <boost/type_traits.hpp>

#include <string>

#include <assert.h>

 

#define NVP(name) #name, name

#define SerializenvP(name) Serialize(NVP(name))

 

#define DeSerializeNVP(name) DeSerialize(NVP(name))

 

class JsonSerializerHelper {

 private:

  //SFINAE garbage to detect whether a type has a Serialize member

  struct serialize_not_found {};

  typedef serialize_not_found SerializeNotFound;

  struct SerializeFound { char x[2]; };

 

  template<typename T, void (T::*)(JsonSerializerHelper&) const>

  struct Serializetester { };

    

  template<typename T>

  static SerializeFound SerializeTest(SerializeTester<T, &T::Serialize>*);  

  template<typename T>

  static SerializeNotFound SerializeTest(...);

 

  template<typename T>

  struct HasSerialize

  {

    static const bool value = sizeof(SerializeTest<T>(0)) == sizeof(SerializeFound);

  };

 

  //Serialize using a free function defined for the type (default fallback)

  template<typename TValue>

  void Serializeimpl(const TValue& value,

    typename boost::disable_if<HasSerialize<const TValue> >::type* dummy = 0)

  {

    //prototype for the serialize free function, so we will get a link error if it's missing

    //this way we don't need a header with all the serialize functions for misc types (eg math)

    void SerializeFail(const TValue&, JsonSerializerHelper&);

 

    SerializeFail(value, *this);

  }

 

  //Serialize using a member function Serialize(JsonSerializer&)

  template<typename TValue>

  void SerializeImpl(const TValue& value, typename boost::enable_if<HasSerialize<const TValue> >::type* dummy = 0)

  {

    value.Serialize(*this);

  }

 

 private:

  //  

  struct deserialize_not_found {};

  typedef deserialize_not_found DeSerializeNotFound;

 

  struct DeSerializeFound { char x[2]; };  

 

  template<typename T, void (T::*)(const JsonSerializerHelper&)>

  struct DeSerializeTester { };

  template<typename T>

  static DeSerializeFound DeSerializeTest(DeSerializeTester<T, &T::DeSerialize>*);  

  template<typename T>

  static DeSerializeNotFound DeSerializeTest(...);

 

  template<typename T>

  struct HasDeSerialize

  {

    static const bool value = sizeof(DeSerializeTest<T>(0)) == sizeof(DeSerializeFound);

  };

 

  //Serialize using a free function defined for the type (default fallback)

  template<typename TValue>

  void DeSerializeImpl(TValue& value,

    typename boost::disable_if<HasDeSerialize<TValue> >::type* dummy = 0) const

  {

    void DeSerializeFail(TValue&, const JsonSerializerHelper&);

 

    DeSerializeFail(value, *this);

  }

 

  //Serialize using a member function Serialize(JsonSerializer&)

  template<typename TValue>

  void DeSerializeImpl(TValue& value, typename boost::enable_if<HasDeSerialize<TValue> >::type* dummy = 0) const

  {

    value.DeSerialize(*this);

  }

public:

  JsonSerializerHelper()

  { }

 

  template<typename TKey, typename TValue>

  void Serialize(TKey key, const TValue& value, typename boost::enable_if<boost::is_class<TValue> >::type* dummy = 0)

  {

    // class to json

    JsonSerializerHelper subVal;

    subVal.SerializeImpl(value); 

    JsonValue[key] = subVal.JsonValue;

  }

 

  template<typename TKey, typename TValue>

  void DeSerialize(TKey key, TValue& value, typename boost::enable_if<boost::is_class<TValue> >::type* dummy = 0) const

  {

    // JSON to class

    JsonSerializerHelper subVal;    

    subVal.JsonValue = JsonValue[key];

    subVal.DeSerializeImpl(value);

  }

 

  template<typename TKey>

  void Serialize(TKey key, const Json::Value& value)

  {

    Write(key, value);

  }

 

  template<typename TKey>

  void DeSerialize(TKey key, Json::Value& value) const

  {

    Read(key, value);

  }

  //Serialize a string value

  template<typename TKey>

  void Serialize(TKey key, const std::string& value)

  {    

    Write(key, value);

  }

 

  //DeSerialize a string value

  template<typename TKey>

  void DeSerialize(TKey key, std::string& value) const

  {    

    Read(key, value);

  }

 

  //Serialize a non class type directly using JsonCpp

  template<typename TKey, typename TValue>

  void Serialize(TKey key, const TValue& value, typename boost::enable_if<boost::is_fundamental<TValue> >::type* dummy = 0)

  {    

    Write(key, value);

  }

 

  template<typename TKey, typename TValue>

  void DeSerialize(TKey key, TValue& value, typename boost::enable_if<boost::is_fundamental<TValue> >::type* dummy = 0) const

  {

    Read(key, value);

  }

 

  //Serialize an enum type to JsonCpp 

  template<typename TKey, typename TEnum>

  void Serialize(TKey key, const TEnum& value, typename boost::enable_if<boost::is_enum<TEnum> >::type* dummy = 0)

  {

    int ival = (int) value;    

    Write(key, ival);    

  }

 

  template<typename TKey, typename TEnum>

  void DeSerialize(TKey key, TEnum& value, typename boost::enable_if<boost::is_enum<TEnum> >::type* dummy = 0) const

  {

    int ival = (int) value;

    Read(key, ival);

    value = (TEnum) ival;

  }

 

  template<typename TKey, typename TValue>

  void Serialize(TKey key, const std::vector<TValue>& vec)

  {

    Write(key, vec.begin(), vec.end());        

  }

 

  template<typename TKey, typename TValue>

  void DeSerialize(TKey key, std::vector<TValue>& vec) const

  {

    JsonSerializerHelper subVal;

    subVal.JsonValue = JsonValue[key];

    subVal.Read(vec);

  }

 

  Json::Value JsonValue;

 

private:

  template<typename TKey, typename TValue>

  void Write(TKey key, const TValue& value)

  {

    JsonValue[key] = value;

  }

 

  template<typename TKey, typename TValue>

  void Write(TKey key, const std::vector<TValue>& vec)

  {

 

    JsonSerializerHelper subVal;

    int index = 0;

    for(typename std::vector<TValue>::const_iterator it = vec.begin(); it != vec.end(); ++it)

    {

      subVal.Serialize(index, *it);

      ++index;

    }

    JsonValue[key] = subVal.JsonValue;

  }

 

  template<typename TKey, typename TItor>

  void Write(TKey key, TItor First, TItor last)

  {

    JsonSerializerHelper subVal;

    int index = 0;

    for(TItor it = first; it != last; ++it)

    {

      subVal.Serialize(index, *it);

      ++index;

    }

    JsonValue[key] = subVal.JsonValue;

  }

 

 

  template<typename TKey, typename TValue>

  void Read(TKey key, TValue& value, typename boost::enable_if<boost::is_arithmetic<TValue> >::type* dummy = 0) const

  {    

    int ival = 0 ;

    if (JsonValue[key].isNumeric()){

      ival = JsonValue[key].asInt();

    } else {

      //assert(false);

    }

    value = (TValue) ival;

  }

 

  template<typename TKey, typename TValue>

  void Read(TKey key, TValue& value) const

  {

    value = JsonValue[key];

  }

 

  template<typename TKey>

  void Read(TKey key, bool& value) const

  {

    bool bval = false ;

    bval = JsonValue[key].asBool();    

    value = bval;

  }

 

  template<typename TKey>

  void Read(TKey key, int& value) const

  {

    int ival = 0 ;

    if (JsonValue[key].isNumeric()){

      ival = JsonValue[key].asInt();

    } else if (JsonValue[key].isString()){

      ival = atoi(JsonValue[key].asCString());         

    } else {

      //assert(false);

    }

    value = ival;

  }

 

  template<typename TKey>

  void Read(TKey key, unsigned int& value) const

  {

    unsigned int uival = 0 ;

    if (JsonValue[key].isNumeric()){

      uival = JsonValue[key].asUInt();

    } else if (JsonValue[key].isString()){

      uival = atoi(JsonValue[key].asCString());         

    } else {

      //assert(false);

    }

    value = uival;

  }

 

  template<typename TKey>

  void Read(TKey key, float& value) const

  {

    float fval = 0.0 ;

    if (JsonValue[key].isNumeric()){

      fval = JsonValue[key].asFloat();

    } else if (JsonValue[key].isString()){

      fval = atof(JsonValue[key].asCString());    

    } else {

      //assert(false);

    }

    value = fval;

  }

 

  template<typename TKey>

  void Read(TKey key, double& value) const

  {

    double dval = 0.0 ;

    if (JsonValue[key].isNumeric()){

      dval = JsonValue[key].asDouble();

    } else if (JsonValue[key].isString()){

      dval = atof(JsonValue[key].asCString());    

    } else {

      //assert(false);

    }

    value = dval;

  }

 

  template<typename TKey>

  void Read(TKey key, std::string& value) const

  {

    std::string sval = "" ;

    if (JsonValue[key].isString()){

      sval = JsonValue[key].asString();

    } else {

      //assert(false);

    }

    value =  sval;

  }

 

  template<typename TValue>

  void Read(std::vector<TValue>& vec) const

  {

    if(!JsonValue.isArray())

      return;

 

    vec.clear();

    vec.reserve(vec.size() + JsonValue.size());

    for(int i = 0; i < JsonValue.size(); ++i)

    {

      TValue val;

      DeSerialize(i, val);

      vec.push_back(val);

    }

  }

};

#endif //JSON_SERIALIZER_HELPER_HPP

复制代码

 

 

 

 

 我对原来的基础上进行了稍微改良,把DeSerialize 和Serialize分离了,每个类需要实现这两个接口,这个工具通过函数重载模板匹配对序列化做了统一的接口

 

【生成Cpp代码】

我们对json文件进行解析,json的dict对应c++的类,字典类的某个字段相应的类型对应c++类型,用key值作为class类型名,

 

【样例】

 

  json

 

 

复制代码

{

   "image": {

       "width":  800,

       "height": 600,

       "title":  "View from 15th Floor",

       "thumbnail": {

           "url":    "https://www.example.com/image/481989943",

           "height": 125,

           "width":  "100"

       },

       "ids": [116, 943, 234, 38793]

     }

}

复制代码

 

 

  c++ cpp

 

 

 

 

复制代码

// Don't Edit it

#ifndef TEST_H_

#define TEST_H_

 

#include <string>

#include <vector>

#include <lib_json/json_lib.h>

 

 

class JsonSerializerHelper;

 

namespace net {

namespace test {

 

 

class Thumbnail {

 public:

    Thumbnail();

    ~Thumbnail(){}

 

    const std::string& get_url() { return url;}

    const std::string& get_url() const { return url;}

    void set_url(const std::string& url_a) {

         url = url_a; 

    }

 

    const std::string& get_width() { return width;}

    const std::string& get_width() const { return width;}

    void set_width(const std::string& width_a) {

         width = width_a; 

    }

 

    const int& get_height() { return height;}

    const int& get_height() const { return height;}

    void set_height(const int& height_a) {

         height = height_a; 

    }

 

 

    void Serialize(JsonSerializerHelper& json_serializer_helper) const;

    void DeSerialize(const JsonSerializerHelper& json_serializer_helper);

 

 private:

     std::string url;

     std::string width;

     int height;

 

}; // class Thumbnail

 

class Image {

 public:

    Image();

    ~Image(){}

 

    const std::vector<int>& get_ids() { return ids;}

    const std::vector<int>& get_ids() const { return ids;}

    void set_ids(const std::vector<int>& ids_a) {

         ids = ids_a; 

    }

 

    const int& get_width() { return width;}

    const int& get_width() const { return width;}

    void set_width(const int& width_a) {

         width = width_a; 

    }

 

    const std::string& get_title() { return title;}

    const std::string& get_title() const { return title;}

    void set_title(const std::string& title_a) {

         title = title_a; 

    }

 

    Thumbnail& get_thumbnail() { return thumbnail;}

    const Thumbnail& get_thumbnail() const { return thumbnail;}

    void set_thumbnail(const Thumbnail& thumbnail_a) {

         thumbnail = thumbnail_a; 

    }

 

    const int& get_height() { return height;}

    const int& get_height() const { return height;}

    void set_height(const int& height_a) {

         height = height_a; 

    }

 

 

    void Serialize(JsonSerializerHelper& json_serializer_helper) const;

    void DeSerialize(const JsonSerializerHelper& json_serializer_helper);

 

 private:

     std::vector<int> ids;

     int width;

     std::string title;

     Thumbnail thumbnail;

     int height;

 

}; // class Image

 

class Test {

 public:

    Test();

    ~Test(){}

 

    Image& get_image() { return image;}

    const Image& get_image() const { return image;}

    void set_image(const Image& image_a) {

         image = image_a; 

    }

 

 

    void Serialize(JsonSerializerHelper& json_serializer_helper) const;

    void DeSerialize(const JsonSerializerHelper& json_serializer_helper);

 

 private:

     Image image;

 

}; // class Test

 

} // namespace test

} // namespace net

#endif // TEST_H_

复制代码

 

 

【注意】

  1.因为json支持数组支持不同类型的值,但c++不支持,所有我这里数组里面只认识写简单的类型,但要类型一致,

 

      2.这里用key的首字母大写做类型名,用key值作为对象名,所以一定要保证首字母key是小写的

 

      3.因为不同json可能有相同的key值,所以我针对不同的json加了namespace 保护

 

  以上的问题,我们在开发过程中,这样的需求很少,即使有,我们也去避开这样的问题。不是去正面对抗这样的问题。因为我要自动生成解析代码,自动生成好处是自动更新,无需人为参与。

觉得可用,就经常来吧! 脚本宝典 欢迎评论哦! js脚本,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的javascript代码实例教程-json 对c++类的序列化(自动生成代码)全部内容,希望文章能够帮你解决javascript代码实例教程-json 对c++类的序列化(自动生成代码)所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。