Google APIs Client Library for C++
jsoncpp_data.h
Go to the documentation of this file.
00001 /*
00002  * \copyright Copyright 2013 Google Inc. All Rights Reserved.
00003  * \license @{
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  *
00017  * @}
00018  */
00019 
00020 /*
00021  * @defgroup DataLayerJsonCpp Data Layer - JSON Support (using JsonCpp)
00022  *
00023  * The current implementation of JSON support uses the third-party JsonCpp
00024  * lirary (http://jsoncpp.sourceforge.net/) which has some issues that leak
00025  * into the interface. Therefore, I'm grouping these into a 'JsonCpp' module.
00026  *
00027  * The design of the JsonCpp sub-module makes pragmatic tradeoffs in order
00028  * to use this existing implementation. The main thing to be aware of is that
00029  * the signatures of the class methods in this  module often use call by
00030  * value-result semantics rather than call by reference as you would expect.
00031  * However, the internal implementation is often actually call by reference.
00032  * So the semantics (and performance) are similar to call-by reference but
00033  * the code feels like cal-by value. This is unfortunate and I hope to address
00034  * it in future releases.
00035  */
00036 
00037 #ifndef APISERVING_CLIENTS_CPP_DATA_JSONCPP_DATA_H_
00038 #define APISERVING_CLIENTS_CPP_DATA_JSONCPP_DATA_H_
00039 #include <string>
00040 using std::string;
00041 #include <utility>
00042 using std::make_pair;
00043 using std::pair;
00044 #include <vector>
00045 using std::vector;
00046 
00047 #include "googleapis/client/data/serializable_json.h"
00048 #include "googleapis/client/data/jsoncpp_data_helpers.h"
00049 #include <glog/logging.h>
00050 #include "googleapis/base/macros.h"
00051 #include <json/json.h>
00052 namespace googleapis {
00053 
00054 namespace client {
00055 
00056 class DataReader;
00057 
00058 // Forward declaration
00059 template<typename T> class JsonCppConstIndexIterator;
00060 template<typename T> class JsonCppConstAssociativeIterator;
00061 
00062 /*
00063  * Base class for data objects using JsonCpp for underlying state.
00064  * @ingroup DataLayerJsonCpp
00065  *
00066  * Class instances are either const or mutable depending on how they are
00067  * constructed. If constructed with a const reference, the instance will not
00068  * allow direct mutation. If constructed with a pointer, the instance will
00069  * allow mutation. It doesnt necessarily have to be like this, just seems like
00070  * a reasonable safety mechanism given the wrapper ipmlementation strategy.
00071  *
00072  * The objects are intended to be used in a call-by-value / value-result syntax
00073  * however the "values" are actually references so semantics are actually
00074  * call-by-reference. Admitedly this is unfortunate (i.e. weird) but it is to
00075  * allow object wrappers to be used in a complete and uniform way when
00076  * accessing and modifying complex composite objects through their various
00077  * parts. Since the wrapper object state is just a pointer (and a bool) the
00078  * copying syntax should not add much runtime overhead.
00079  *
00080  * Keeping all the state in the Json::Value object will likely add runtime
00081  * overhead however. Rather than attributes (of derived classes) being inlined
00082  * member variables, they will be [] operator lookups on string names. The
00083  * tradeoff here is for completeness, correctness, and internal implementation
00084  * convienence in the short term to get things up and running more quickly to
00085  * play with and understand strategic issues beyond performance.
00086  *
00087  * Keeping all the state together allows unknown attributes to be first-class
00088  * citizens along with known ones. Serialization, iteration, and so forth are
00089  * already handled (and in an open soure library) by jsoncpp. Presumably since
00090  * this is cheap to implement, it will be cheap to throw away and replace,
00091  * investing the effort for runtime efficiency (or finding another package)
00092  * at some future point down the road when it is a more pressing impedement.
00093  *
00094  * This class is not thread-safe.
00095  */
00096 class JsonCppData : public SerializableJson {
00097  public:
00098   /*
00099    * Standard constructor for an immutable instances.
00100    *
00101    * @param[in] value Provides the underlying JsonCpp storage.
00102    *            The lifetime of 'value' must be retained over the lifetime of
00103    *            this instance, however the state can change internally.
00104    */
00105   explicit JsonCppData(const Json::Value& value);
00106 
00107   /*
00108    * Standard constructor for mutable instances.
00109    *
00110    * @param[in] value Provides the underlying JsonCpp storage.
00111    *                  Ownership of 'value' is retained by the caller and
00112    *                  must live beyond the lifecycle of this instance.
00113    */
00114   explicit JsonCppData(Json::Value* value);
00115 
00116   /*
00117    * Standard destructor.
00118    */
00119   virtual ~JsonCppData();
00120 
00121   /*
00122    * Restores the state of this object from the JSON in the given std::istream.
00123    *
00124    * @param[in] stream The stream to read from.
00125    * @return ok or explaination of failure.
00126    *
00127    * @see LoadFromJsonReader
00128    */
00129   virtual util::Status LoadFromJsonStream(std::istream* stream);
00130 
00131   /*
00132    * Stores the state of this object as JSON in the given std::ostream.
00133    *
00134    * @param[in] stream The stream to write to.
00135    * @return ok or explaination of failure.
00136    *
00137    * @see MakeJsonReader
00138    */
00139   virtual util::Status StoreToJsonStream(std::ostream* stream) const;
00140 
00141   /*
00142    * Clears this instance state to an empty object.
00143    */
00144   virtual void Clear();
00145 
00146   /*
00147    * Restores the state of this object from the JSON in the given reader.
00148    *
00149    * @param[in] reader The byte-sequence to read from.
00150    * @return ok or explaination of failure.
00151    */
00152   virtual util::Status LoadFromJsonReader(DataReader* reader);
00153 
00154   /*
00155    * Serializes the object into a JSON byte stream.
00156    *
00157    * @return A standard reader interface around the JSON encoded object.
00158    */
00159   virtual DataReader* MakeJsonReader() const;
00160 
00161   /*
00162    * Copies state from another instance into this one.
00163    *
00164    * This will preserve the existing IsMutable-ness of this instance.
00165    *
00166    * @param[in] from The state to copy from.
00167    */
00168   void CopyFrom(const JsonCppData& from) {
00169     *MutableStorage() = from.Storage();
00170   }
00171 
00172   /*
00173    * Determines if this instance is mutable or not.
00174    *
00175    * Mutability is determined by which constructor was used.
00176    *
00177    * @return true if the instance is mutable.
00178    */
00179   bool IsMutable() const { return is_mutable_; }
00180 
00181   /*
00182    * Determines if the represented JSON value is NULL.
00183    *
00184    * @return true if the underlying Json::Value denotes a null value.
00185    */
00186   bool IsNull() const { return value_->isNull(); }
00187 
00188   /*
00189    * Ensures the instance is mutable or terminate if not.
00190    *
00191    * If the instance is not mutable this call will CHECK-fail and
00192    * terminate the program. It is only intended to make assertions
00193    * that indicate programming errors.
00194    */
00195   void CheckIsMutable() const { CHECK(is_mutable_); }
00196 
00197   /*
00198    * Returns reference to the Json::Value instance used for storage.
00199    *
00200    * @return The instance bound in the constructor.
00201    */
00202   const Json::Value& Storage() const                { return *value_; }
00203 
00204   /*
00205    * Returns reference to the Json::Value instance used for storage.
00206    *
00207    * This will create a new subcomponent if one did not already exist.
00208    *
00209    * @param[in] key The JSON name of the desired subcomponent.
00210    *
00211    * @return The instance might be Json::Value::isNull but will be valid.
00212    */
00213   const Json::Value& Storage(const char* key) const { return (*value_)[key]; }
00214 
00215   /*
00216    * Returns a pointer to the storage bound in the constructor.
00217    *
00218    * This method will CHECK fail if the instance is immutable.
00219    */
00220   Json::Value* MutableStorage() {
00221     CheckIsMutable();
00222     return value_;
00223   }
00224 
00225   /*
00226    * Returns a pointer to the storage for the named subcomponent.
00227    *
00228    * This method will CHECK fail if the instance is immutable.
00229    */
00230   Json::Value* MutableStorage(const char* key) {
00231     CheckIsMutable();
00232     return &(*value_)[key];
00233   }
00234 
00235   /*
00236    * Determines if the object instances are equivalent.
00237    */
00238   bool operator==(const JsonCppData& other) const {
00239     return *value_ == *other.value_;
00240   }
00241 
00242  private:
00243   bool is_mutable_;
00244   Json::Value* value_;  // reference is not owned
00245 
00246   // Disallow assigning but preserve copying because we'll need to return
00247   // wrapped object instances from the APIs due to the call-by-value
00248   // constraints inherited from the underlying JsonCpp API.
00249   void operator=(const JsonCppData& obj);
00250 };
00251 
00252 /*
00253  * Base class template for a JsonCppData object that is an array.
00254  * @ingroup DataLyaerJsonCpp
00255  *
00256  * Arrays currently follow the JsonCpp implementation where they grow on
00257  * demand. Accessing an element wil create it if it did not already exist.
00258  *
00259  * This class is not thread-safe.
00260  *
00261  * @todo(ewiseblatt): 20120825
00262  * Probably change this so the arrays are fixed size unless you resize the
00263  * array or append/remove from it. That means get/set should rangecheck.
00264  */
00265 template<typename T>
00266 class JsonCppArray : public JsonCppData {
00267  public:
00268   typedef JsonCppConstIndexIterator<T> const_iterator;
00269 
00270   /*
00271    * Standard constructor for an immutable array.
00272    *
00273    * @param[in] value Provides the underlying storage for the array.
00274    */
00275   explicit JsonCppArray(const Json::Value& value)
00276     : JsonCppData(value) {
00277   }
00278 
00279   /*
00280    * Standard constructor for a mutable array.
00281    *
00282    * @param[in] value Provides the underlying storage for the array.
00283    */
00284   explicit JsonCppArray(Json::Value* value)
00285     : JsonCppData(value) {
00286   }
00287 
00288   /*
00289    * Determines if array is empty or not.
00290    */
00291   bool empty() const { return Storage().size() == 0; }
00292 
00293   /*
00294    * Determines the number of elements currently in the array.
00295    */
00296   int size() const { return Storage().size(); }
00297 
00298   /*
00299    * Gets the [immutable] underlying JsonCpp storage for a given array element.
00300    *
00301    * @see as_object
00302    * @see get
00303    */
00304   const Json::Value& as_value(int i) const { return Storage()[i]; }
00305 
00306   /*
00307    * Gets the [mutable] underlying JsonCpp storage for a given array element.
00308    *
00309    * This method will CHECK fail if the array is not mutable.
00310    *
00311    * @see as_mutable_object
00312    * @see mutable_get
00313    */
00314   Json::Value* as_mutable_value(int i)    { return &(*MutableStorage())[i]; }
00315 
00316   /*
00317    * Gets the [immutable] JsonCppData instance wrapping a given array element.
00318    *
00319    * @see as_value
00320    * @see get
00321    */
00322   const JsonCppData as_object(int i) const {
00323     return JsonCppData(as_value(i));
00324   }
00325 
00326   /*
00327    * Gets the [mutable] JsonCppData instance wrapping a given array element.
00328    *
00329    * @see as_mutable_value
00330    * @see mutable_get
00331    */
00332   JsonCppData as_mutable_object(int i) {
00333     return JsonCppData(as_mutable_value(i));
00334   }
00335 
00336   /*
00337    * Returns the starting point for iterating over the elements.
00338    *
00339    * Unfortunately this data model only permits const iterators
00340    * because of the call-by-value-result nature of the api. We cant modify
00341    * the elements unless we create a storage iterator that iterates over the
00342    * storage (which you can already do by saying MutableStorage()->begin/end()
00343    */
00344   const_iterator begin() const { return const_iterator(Storage().begin()); }
00345 
00346   /*
00347    * Returns the ending poitn when iterating over the elements
00348    */
00349   const_iterator end() const   { return const_iterator(Storage().end()); }
00350 
00351   /*
00352    * Changes the value for the given element.
00353    *
00354    * This method will CHECK-fail if the array is not mutable.
00355    *
00356    * @param[in] i The index to change will be added if it was not present.
00357    * @param[in] value The value to copy.
00358    */
00359   void set(int i, const T& value) {
00360     SetJsonValueFromCppValueHelper<T>(value, as_mutable_value(i));
00361   }
00362 
00363   /*
00364    * Returns the value for the given index.
00365    * @param[in] i The element index to get.
00366    */
00367   const T get(int i) const {
00368     return JsonValueToCppValueHelper<T>(as_value(i));
00369   }
00370 
00371   /*
00372    * Returns a mutable value for the given index.
00373    *
00374    * This method will CHECK-fail if the array is not mutable.
00375    *
00376    * @return The value as opposed to a pointer. See the class description
00377    *         for more information about the calling conventions.
00378    *         Although the value is not a pointer, it will be mutable if
00379    *         <code>T</code> denotes a <code>JsonCppObject</code>. For
00380    *         primitive types (and strings) this method will return copy
00381    *         that will not actually mutate the underlying element.
00382    */
00383   T mutable_get(int i) {
00384     return JsonValueToMutableCppValueHelper<T>(as_mutable_value(i));
00385   }
00386 
00387   /*
00388    * Provides syntactic sugar for get using [] operator overloading.
00389    */
00390   const T operator[](int i) const { return get(i); }
00391 
00392   /*
00393    * Provides syntactic sugar for mutable_get using [] operator overloading.
00394    */
00395   T operator[](int i) { return mutable_get(i); }
00396 
00397 
00398   /*
00399    * Imports data from a C++ vector into this instance.
00400    *
00401    * This method will clear the current data before importing the new.
00402    *
00403    * @param[in] array The vector to import from.
00404    */
00405   void Import(const vector<T>& array) {
00406     Clear();
00407     MutableStorage()->resize(array.size());
00408     for (int i = 0; i < array.size(); ++i) {
00409       set(i, array[i]);
00410     }
00411   }
00412 
00413   /*
00414    * Imports data from a C++ aray into this instance.
00415    *
00416    * This method will clear the current data before importing the new.
00417    *
00418    * @param[in] array The array to import from.
00419    * @param[in] len The number of elements int he array to import.
00420    */
00421   void Import(const T* array, int len) {
00422     Clear();
00423     for (int i = 0; i < len; ++i) {
00424       set(i, array[i]);
00425     }
00426   }
00427 
00428   /*
00429    * Exports data from this instance into a given C++ vector.
00430    *
00431    * This will clear the array before exporting.
00432    */
00433   void Export(vector<T>* array) const { Export(0, size(), array); }
00434 
00435   /*
00436    * Exports a range of data from this instance into a given C++ vector.
00437    *
00438    * This will clear the array before exporting.
00439    *
00440    * @param[in] offset The first index in this array to eport
00441    * @param[in] count The number of elements to export
00442    * @param[out] array The array to write to will be cleared before writing.
00443    *             The element at offset will be written into the 0'th element.
00444    * @return false if the existing bounds of this array are not consistent
00445    * with the arguments.
00446    */
00447   bool Export(int offset, int count, vector<T>* array) const {
00448     const Json::Value& json = Storage();
00449     if (offset + count > json.size()) return false;
00450 
00451     array->clear();
00452     array->resize(count);
00453     for (int i = 0; i < count; ++i) {
00454       (*array)[i] = get(offset + i);
00455     }
00456     return true;
00457   }
00458 
00459   /*
00460    * Exports a range of data from this instance into a given C++ array.
00461    *
00462    * @param[in] offset The first index in this array to eport
00463    * @param[in] count The number of elements to export
00464    * @param[out] array The caller should ensure that there are count elements
00465    *             allocated in the array.
00466    * @return false if the existing bounds of this array are not consistent
00467    * with the arguments.
00468    */
00469   bool Export(int offset, int count, T* array) const {
00470     const Json::Value& json = Storage();
00471     if (offset + count > json.size()) return false;
00472 
00473     for (int i = 0; i < count; ++i) {
00474       array[i] = get(offset + i);
00475     }
00476     return true;
00477   }
00478 };
00479 
00480 
00481 /*
00482  * Denotes a JsonCppData instance that is a dictionary.
00483  * @ingroup DataLayerJsonCpp
00484  *
00485  * The JsonCppData wraps a shared reference to jsoncpp values.
00486  * Multiple objects may reference the same values. A dictionary
00487  * does not have homogenous value types. Usually you want to use
00488  * an associative array instead.
00489  *
00490  * This class is not thread-safe.
00491  *
00492  * @see JsonCppAssociativeArray
00493  */
00494 class JsonCppDictionary : public JsonCppData {
00495  public:
00496   explicit JsonCppDictionary(const Json::Value& value);
00497   explicit JsonCppDictionary(Json::Value* value);
00498 
00499   int size() const { return Storage().size(); }
00500 
00501   bool has(const char* key) const {
00502     return Storage().isMember(key);
00503   }
00504 
00505   void remove(const char* key) {
00506     MutableStorage()->removeMember(key);
00507   }
00508 
00509   // NOTE(ewiseblatt): 20120827
00510   // The data value here is mutable. Currently there isnt a way to have
00511   // just const values in a dictionary.
00512   void put_value(const char* key, const Json::Value& data) {
00513     *MutableStorage(key) = data;
00514   }
00515 
00516   void put_object(const char* key, const JsonCppData& value) {
00517     *MutableStorage(key) = value.Storage();
00518   }
00519 
00520   const Json::Value& as_value(const char* key) const { return Storage(key); }
00521   const JsonCppData as_object(const char* key) const {
00522     return JsonCppData(Storage(key));
00523   }
00524 
00525   JsonCppData mutable_object(const char* key) {
00526     return JsonCppData(MutableStorage(key));
00527   }
00528 };
00529 
00530 /*
00531  * Denotes an associative array from string to values of type <code>T</code>.
00532  * @ingroup DataLayerJsonCpp
00533  *
00534  * This class is not thread-safe.
00535  */
00536 template<typename T>
00537 class JsonCppAssociativeArray : public JsonCppDictionary {
00538  public:
00539   typedef JsonCppConstAssociativeIterator<T> const_iterator;
00540 
00541   explicit JsonCppAssociativeArray(const Json::Value& value)
00542     : JsonCppDictionary(value) {
00543   }
00544 
00545   explicit JsonCppAssociativeArray(Json::Value* value)
00546     : JsonCppDictionary(value) {
00547   }
00548 
00549   bool get(const char* key, T* value) const {
00550     CHECK_NOTNULL(value);
00551     Json::Value v = Storage().get(key, Json::Value::null);
00552     if (v == Json::Value::null) {
00553       ClearCppValueHelper(value);
00554       return false;
00555     }
00556     SetCppValueFromJsonValueHelper(v, value);
00557     return true;
00558   }
00559 
00560   void put(const char* key, const T& value) {
00561     SetJsonValueFromCppValueHelper(value, MutableStorage(key));
00562   }
00563 
00564   const_iterator begin() const { return const_iterator(Storage().begin()); }
00565   const_iterator end() const   { return const_iterator(Storage().end()); }
00566 };
00567 
00568 
00569 /*
00570  * Helper class for constructing new top-level JsonCppData instances.
00571  * @ingroup DataLayerJsonCpp
00572  *
00573  * The base JsonCppData class requires storage managed externally. When
00574  * creating new top-level instances you do not necessarily have a Json::Value
00575  * instance already nor do you want to worry about managing one.
00576  *
00577  * This capsule creates a specialization of any standard class derived from
00578  * JsonCppData that provides its own storage for a default constructor.It is
00579  * only inteded for actually instantiating new instances. When passing them
00580  * around, the BASE class should be used in the interfaces.
00581  */
00582 template<typename BASE>
00583 class JsonCppCapsule : public BASE {
00584  public:
00585   /*
00586    * Default constructor
00587    */
00588   JsonCppCapsule() : BASE(&storage_) {}
00589 
00590   /*
00591    * Standard destructor
00592    */
00593   virtual ~JsonCppCapsule() {}
00594 
00595  private:
00596   Json::Value storage_;
00597   DISALLOW_COPY_AND_ASSIGN(JsonCppCapsule);
00598 };
00599 
00600 /*
00601  * A helper class for index or key-based iterators.
00602  *
00603  * It just delegates to the base JsonCpp iterator.
00604  *
00605  * Note that because the data model is call-by-value-result theiterator can
00606  * only return copies and not references. Therefore we'll not be able to
00607  * modify values in place (i.e. this will not support a non-const iterator)
00608  */
00609 template<typename DATA, typename ITERATOR>
00610 class JsonCppAbstractIterator {
00611  public:
00612   typedef typename ITERATOR::size_t size_t;
00613   typedef JsonCppAbstractIterator<DATA, ITERATOR> SelfType;
00614 
00615   explicit JsonCppAbstractIterator(const SelfType& copy) : it_(copy.it_) {}
00616   ~JsonCppAbstractIterator() {}
00617 
00618   SelfType& operator=(const JsonCppAbstractIterator& copy) {
00619     it_ = copy.it_;
00620     return *this;
00621   }
00622   SelfType& operator++() {
00623     ++it_;
00624     return *this;
00625   }
00626   bool operator==(const SelfType& it) const {
00627     return it_ == it.it_;
00628   }
00629   bool operator!=(const SelfType& it) const {
00630     return it_ != it.it_;
00631   }
00632 
00633  protected:
00634   explicit JsonCppAbstractIterator(const ITERATOR& it) : it_(it) {}
00635   ITERATOR it_;
00636 };
00637 
00638 /*
00639  * Iterator for index-based JsonCppDataArray.
00640  * @ingroup DataLayerJsonCpp
00641  *
00642  * Provides access to the index in the array which might be helpful for
00643  * making modifications directly into the array if needed,
00644  * since we cannot support non-const iterators.
00645  */
00646 template<typename T>
00647 class JsonCppConstIndexIterator
00648     : public JsonCppAbstractIterator<T, Json::Value::const_iterator> {
00649  public:
00650   typedef JsonCppConstIndexIterator<T> SelfType;
00651   typedef T reference;  // Note we're using copy-by-value references
00652 
00653   JsonCppConstIndexIterator(const JsonCppConstIndexIterator<T>& copy)
00654       : JsonCppAbstractIterator<T, Json::Value::const_iterator>(copy) {}
00655   ~JsonCppConstIndexIterator() {}
00656 
00657   reference operator*() const {
00658     return JsonValueToCppValueHelper<T>(
00659         *JsonCppAbstractIterator<T, Json::Value::const_iterator>::it_);
00660   }
00661   int index() const {
00662     return JsonCppAbstractIterator<
00663       T, Json::Value::const_iterator>::it_.index(); }
00664 
00665  private:
00666   friend class JsonCppArray<T>;
00667   explicit JsonCppConstIndexIterator(const Json::Value::const_iterator& it)
00668       : JsonCppAbstractIterator<T, Json::Value::const_iterator>(it) {}
00669 };
00670 
00671 /*
00672  * Iterator for JsonCppDataAssociativeArray.
00673  * @ingroup DataLayerJsonCpp
00674  */
00675 template<typename T>
00676 class JsonCppConstAssociativeIterator
00677     : public JsonCppAbstractIterator<pair<const string, T>,
00678                                      Json::Value::const_iterator> {
00679  public:
00680   typedef JsonCppConstAssociativeIterator<T> SelfType;
00681   typedef pair<const string, T> reference;
00682   typedef JsonCppAbstractIterator<pair<const string, T>,
00683                                   Json::Value::const_iterator> SuperClass;
00684 
00685   JsonCppConstAssociativeIterator(
00686       const JsonCppConstAssociativeIterator<T>& copy) : SuperClass(copy) {
00687   }
00688   ~JsonCppConstAssociativeIterator() {}
00689 
00690   // If you only care about one part of the pair, consider key() or value().
00691   reference operator*() const {
00692     return make_pair(key(), value());
00693   }
00694 
00695   // This returns a copy of the string, not a reference to the string.
00696   // Unfortunately this is an implementation detail caused by limitations
00697   // of the underlying data model.
00698   const string key() const {
00699     // The iterator retuns a local object so the CString/string values
00700     // disappear ones it leaves scope, forcing us to have to return a copy.
00701     const Json::Value& temp = SuperClass::it_.key();
00702     return temp.asString();
00703   }
00704 
00705   T value() const { return JsonValueToCppValueHelper<T>(*SuperClass::it_); }
00706 
00707  private:
00708   friend class JsonCppAssociativeArray<T>;
00709   explicit JsonCppConstAssociativeIterator(
00710       const Json::Value::const_iterator& it) : SuperClass(it) {
00711   }
00712 };
00713 
00714 }  // namespace client
00715 
00716 } // namespace googleapis
00717 #endif  // APISERVING_CLIENTS_CPP_DATA_JSONCPP_DATA_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines