1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/Json.h
12 #ifndef ZYPP_BASE_JSON_H
13 #define ZYPP_BASE_JSON_H
22 #include "zypp/base/Easy.h"
23 #include "zypp/base/String.h"
25 ///////////////////////////////////////////////////////////////////
28 ///////////////////////////////////////////////////////////////////
32 inline static const std::string & nullJSON() { static const std::string _s( "null" ); return _s; }
33 inline static const std::string & trueJSON() { static const std::string _s( "true" ); return _s; }
34 inline static const std::string & falseJSON() { static const std::string _s( "false" ); return _s; }
36 ///////////////////////////////////////////////////////////////////
39 inline std::string strEncode( std::string val_r )
41 typedef unsigned char uchar;
43 std::string::size_type add = 2; // enclosing "s
44 for_( r, val_r.begin(), val_r.end() )
46 if ( uchar(*r) < 32u )
75 val_r.resize( val_r.size() + add, '@' );
76 auto w( val_r.rbegin() );
80 for ( ; r != val_r.rend(); ++r )
82 if ( uchar(*r) < 32u )
84 static const char * digit = "0123456789abcdef";
108 *w++ = digit[uchar(*r) % 15];
109 *w++ = digit[uchar(*r) / 16];
119 switch ( (*w++ = *r) )
123 case '\\': // \-escape
132 } // namespace detail
133 ///////////////////////////////////////////////////////////////////
136 inline std::string toJSON( void ) { return nullJSON(); }
137 inline std::string toJSON( std::nullptr_t ) { return nullJSON(); }
140 inline std::string toJSON( bool val_r ) { return val_r ? trueJSON() : falseJSON(); }
141 inline std::string toJSON( const void * val_r ) { return val_r ? trueJSON() : falseJSON(); }
144 inline std::string toJSON( short val_r ) { return str::numstring( val_r ); }
145 inline std::string toJSON( unsigned short val_r ) { return str::numstring( val_r ); }
146 inline std::string toJSON( int val_r ) { return str::numstring( val_r ); }
147 inline std::string toJSON( unsigned val_r ) { return str::numstring( val_r ); }
148 inline std::string toJSON( long val_r ) { return str::numstring( val_r ); }
149 inline std::string toJSON( unsigned long val_r ) { return str::numstring( val_r ); }
150 inline std::string toJSON( long long val_r ) { return str::numstring( val_r ); }
151 inline std::string toJSON( unsigned long long val_r ){ return str::numstring( val_r ); }
154 inline std::string toJSON( const char val_r ) { return detail::strEncode( std::string( 1, val_r ) ); }
155 inline std::string toJSON( const char * val_r ) { return val_r ? detail::strEncode( val_r ) : nullJSON(); }
156 inline std::string toJSON( const std::string & val_r ){ return detail::strEncode( val_r ); }
158 // container to Array
159 template <class V> std::string toJSON( const std::vector<V> & cont_r );
160 template <class V> std::string toJSON( const std::list<V> & cont_r );
161 template <class V> std::string toJSON( const std::set<V> & cont_r );
164 template <class K, class V> std::string toJSON( const std::map<K,V> & cont_r );
166 /** Type to JSON string representation.
167 * This can be implemented as non-static memberfunction \c asJSON,
168 * or as non-memberfunction \c toJSON;
171 * std::string Type::asJSON() const;
172 * std::string toJSON( const Type & );
176 std::string toJSON( const T & val_r ) { return val_r.asJSON(); }
178 ///////////////////////////////////////////////////////////////////
180 /// \brief JSON representation of datatypes via \ref toJSON
182 /// namespace mynamspace
187 /// std::string toJSON( const Mydata & )
188 /// { return json::Array{ "answer", 42 }.asJSON(); }
191 /// mynamspace::Mydata data;
192 /// json::Object bigone {
193 /// { "mydata", data },
194 /// { "panic", false },
195 /// { "nested", json::Object{ {"one",1}, {"two",2}, {"three",3} } }
198 /// cout << bigone << endl;
200 /// \see http://www.json.org/
201 ///////////////////////////////////////////////////////////////////
204 /** Default ctor (null) */
205 Value() : _data( toJSON() ) {}
208 Value( const Value & rhs ) : _data( rhs._data ) {}
210 /** Ctor creating a JSON representation of \a T via \ref toJSON(T) */
212 Value( const T & val_r ) : _data( toJSON( val_r ) ) {}
214 /** JSON representation */
215 const std::string & asJSON() const
218 /** String representation */
219 const std::string & asString() const
223 std::ostream & dumpOn( std::ostream & str ) const
224 { return str << _data; }
230 /** \relates Value Stream output */
231 inline std::ostream & operator<<( std::ostream & str, const Value & obj )
232 { return obj.dumpOn( str ); }
234 ///////////////////////////////////////////////////////////////////
236 ///////////////////////////////////////////////////////////////////
238 /// \brief JSON string
239 /// Force representation as JSON string, mapping e.g. \c null values
240 /// to an empty string. Maninly used in \ref Object as key.
241 ///////////////////////////////////////////////////////////////////
242 struct String : public Value
244 String() : Value( "" ) {}
245 String( std::nullptr_t ) : Value( "" ) {}
247 String( const char val_r ) : Value( val_r ) {}
248 String( const char * val_r ) : Value( val_r ? val_r : "" ) {}
249 String( const std::string & val_r ): Value( val_r ) {}
252 ///////////////////////////////////////////////////////////////////
254 /// \brief JSON array
255 ///////////////////////////////////////////////////////////////////
260 /** Construct from container iterator */
261 template <class Iterator>
262 Array( Iterator begin, Iterator end )
263 { for_( it, begin, end ) add( *it ); }
265 /** Construct from container initializer list { v1, v2,... } */
266 Array( const std::initializer_list<Value> & contents_r )
267 : Array( contents_r.begin(), contents_r.end() )
270 /** Push JSON Value to Array */
271 void add( const Value & val_r )
272 { _data.push_back( val_r.asJSON() ); }
274 /** \overload from container initializer list { v1, v2,... } */
275 void add( const std::initializer_list<Value> & contents_r )
276 { for_( it, contents_r.begin(), contents_r.end() ) add( *it ); }
278 /** JSON representation */
279 std::string asJSON() const
280 { return str::Str() << *this; }
282 /** String representation */
283 std::string asString() const
287 std::ostream & dumpOn( std::ostream & str ) const
291 str << '[' << *_data.begin();
292 for_( val, ++_data.begin(), _data.end() )
298 std::list<std::string> _data;
301 /** \relates Array Stream output */
302 inline std::ostream & operator<<( std::ostream & str, const Array & obj )
303 { return obj.dumpOn( str ); }
306 std::string toJSON( const std::vector<V> & cont_r )
307 { return json::Array( cont_r.begin(), cont_r.end() ).asJSON(); }
310 std::string toJSON( const std::list<V> & cont_r )
311 { return json::Array( cont_r.begin(), cont_r.end() ).asJSON(); }
314 std::string toJSON( const std::set<V> & cont_r )
315 { return json::Array( cont_r.begin(), cont_r.end() ).asJSON(); }
317 ///////////////////////////////////////////////////////////////////
319 /// \brief JSON object
320 ///////////////////////////////////////////////////////////////////
325 /** Construct from map-iterator */
326 template <class Iterator>
327 Object( Iterator begin, Iterator end )
328 { for_( it, begin, end ) add( it->first, it->second ); }
330 /** Construct from map-initializer list { {k1,v1}, {k2,v2},... } */
331 Object( const std::initializer_list<std::pair<String, Value>> & contents_r )
332 : Object( contents_r.begin(), contents_r.end() )
335 /** Add key/value pair */
336 void add( const String & key_r, const Value & val_r )
337 { _data[key_r.asJSON()] = val_r.asJSON(); }
339 /** \overload from map-initializer list { {k1,v1}, {k2,v2},... } */
340 void add( const std::initializer_list<std::pair<String, Value>> & contents_r )
341 { for_( it, contents_r.begin(), contents_r.end() ) add( it->first, it->second ); }
343 /** JSON representation */
344 std::string asJSON() const
345 { return str::Str() << *this; }
347 /** String representation */
348 std::string asString() const
352 std::ostream & dumpOn( std::ostream & str ) const
357 dumpOn( str << '{' << endl, _data.begin() );
358 for_ ( val, ++_data.begin(), _data.end() )
359 dumpOn( str << ',' << endl, val );
360 return str << endl << '}';
364 std::ostream & dumpOn( std::ostream & str, std::map<std::string,std::string>::const_iterator val_r ) const
365 { return str << val_r->first << ": " << val_r->second; }
367 std::map<std::string,std::string> _data;
370 /** \relates Object Stream output */
371 inline std::ostream & operator<<( std::ostream & str, const Object & obj )
372 { return obj.dumpOn( str ); }
374 template <class K, class V>
375 std::string toJSON( const std::map<K,V> & cont_r )
376 { return json::Object( cont_r.begin(), cont_r.end() ).asJSON(); }
380 ///////////////////////////////////////////////////////////////////
382 ///////////////////////////////////////////////////////////////////
383 #endif // ZYPP_BASE_JSON_H