Json serialization of c ++ classes (automatically generated code)

Source: Internet
Author: User

Motivation: google protobuf was used when writing network protocols. protobuf not only has good performance and scalability, but also has a protoc tool for Automatically Generating c ++ class code, this has indeed brought a lot of convenience to programmers. In the next project, the data is transmitted in json format. Then a tool like protoc is developed to generate c ++ class code based on the json file and generate the serialization code, in this way, the jsonvalue serialization is not required to be scattered everywhere during network writing. [Idea] before writing object-c, if you want to serialize classes, you must implement the NSCoding protocol (interface). This implementation method is very friendly. Similarly, my method is referring to NSCoding. [Code] Here I refer to a netizen's json serialization implementation method. I feel this method is very convenient, it uses templates to recognize built-in types and uses a unified interface for all types: Copy code/** Copyright (c) 2011-2012 Promit Roy ** Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software "), to deal * in the Software without restricti On, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or duplicate * 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 encoded 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 particle 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 The software or the use or other dealings in * the software. */////////////////////////////////////// /// // From: http://ventspace.wordpress.com/2012/10/08/c-json-serialization/// FileName: json_serializer_helper.hpp // Modify: Running in // Date: // Description: // History: // <author> <time> <descript> // wait in 2013/9/22 add //////////////////////// ////////////////// //////////////// // # Ifndef handler # 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 define 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 Seria LizeTest (...); 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 functio N, 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 <cons T TValue >>:: type * dummy = 0) {value. serialize (* this);} private: // struct deserialize_not_found {}; typedef includeserializenotfound; struct DeSerializeFound {char x [2] ;}; template <typename T, void (T:: *) (const initialize &)> struct DeSerializeTester {}; template <typename T> static DeSerializeFound DeSerializeTest (DeSerializeTester <T, & T: DeSerialize> *); template <ty Pename 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) co Nst {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 TVal Ue> 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 {// js On 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);} tem Plate <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; W Rite (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 TKe Y, 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 <typenam E 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]. isSt Ring () {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 <typenam E 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: I have slightly improved the original copy code and separated DeSerialize from Serialize, each class needs to implement these two interfaces. This tool uses the function overload template matching to implement a unified interface for serialization [generate Cpp Code]. We parse the json file, the json dict corresponds to the c ++ class, the corresponding type of a field in the dictionary class corresponds to the c ++ type, and the key value is used as the class type name. [Example] json copy generation Code {"image": {"width": 800, "height": 600, "title": "View from 15th Floor", "thumbnail": {"url ": "http://www.example.com/image/481989943", "height": 125, "width": "100"}, "ids ": [116,943,234,387 93]} copy code c ++ cpp copy code // 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 (Response & Response) const; void DeSerialize (const JsonSerializerHelper & response); 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 & timeout () const {return thumbnail;} void set_thumbnail (const Thumbnail & signature) {thumbnail = thumbnail_a;} const int & get_height () {return height;} const int & get_height () const {return height;} void set_height (const int & height_a) {hei Ght = height_a;} void Serialize (JsonSerializerHelper & inline) const; void DeSerialize (const JsonSerializerHelper & inline); 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 _ copy the code. [note] 1. because json support The array supports different types of values, but c ++ does not. I only know the simple types in the array here, but the types must be consistent. 2. the first letter of the key is used as the type name, and the key value is used as the object name. Therefore, make sure that the first letter of the key is 3 in lower case. because different json files may have the same key value, I have added namespace for different json files to protect the above problems. during the development process, such requirements are rare, we also want to avoid such problems. It's not about confrontation. Because I want to automatically generate resolution code, the advantage of Automatic Generation is automatic update, without human intervention.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.