MythTV  master
jsonSerializer.cpp
Go to the documentation of this file.
1 // Program Name: jsonSerializer.cpp
3 // Created : Nov. 28, 2009
4 //
5 // Purpose : Serialization Implementation for JSON
6 //
7 // Copyright (c) 2005 David Blain <dblain@mythtv.org>
8 //
9 // Licensed under the GPL v2 or later, see LICENSE for details
10 //
12 
13 #include "jsonSerializer.h"
14 #include "libmythbase/mythdate.h"
15 
16 #include <QVariant>
17 
19 //
21 
23 {
24  return "application/json";
25 }
26 
27 
29 //
31 
32 void JSONSerializer::BeginSerialize( QString &/*sName*/ )
33 {
34  m_bCommaNeeded = false;
35 
36  m_stream << "{";
37 }
38 
40 //
42 
44 {
45  m_bCommaNeeded = false;
46 
47  m_stream << "}";
48 
49  m_stream.flush();
50 }
51 
52 
54 //
56 
57 void JSONSerializer::BeginObject( const QString &sName, const QObject */*pObject*/ )
58 {
59  m_bCommaNeeded = false;
60 
61  m_stream << "\"" << sName << "\": {";
62 }
63 
65 //
67 
68 void JSONSerializer::EndObject ( const QString &/*sName*/, const QObject */*pObject*/ )
69 {
70  m_bCommaNeeded = false;
71 
72  m_stream << "}";
73 }
74 
76 //
78 
79 void JSONSerializer::AddProperty( const QString &sName,
80  const QVariant &vValue,
81  const QMetaObject */*pMetaParent*/,
82  const QMetaProperty */*pMetaProp*/ )
83 {
84  if (m_bCommaNeeded)
85  m_stream << ", ";
86 
87  m_stream << "\"" << sName << "\": ";
88 
89  RenderValue( vValue );
90 
91  m_bCommaNeeded = true;
92 }
93 
95 //
97 
98 void JSONSerializer::RenderValue( const QVariant &vValue )
99 {
100 
101  // -----------------------------------------------------------------------
102  // See if this value is actually a child object
103  // -----------------------------------------------------------------------
104 
105  if ( vValue.canConvert< QObject* >())
106  {
107  const QObject *pObject = vValue.value< QObject* >();
108 
109  bool bSavedCommaNeeded = m_bCommaNeeded;
110  m_bCommaNeeded = false;
111 
112  m_stream << "{";
113  SerializeObjectProperties( pObject );
114  m_stream << "}";
115 
116  m_bCommaNeeded = bSavedCommaNeeded;
117 
118  return;
119  }
120 
121  // -----------------------------------------------------------------------
122  // Handle QVariant special cases...
123  // -----------------------------------------------------------------------
124 
125 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
126  auto type = static_cast<QMetaType::Type>(vValue.type());
127 #else
128  auto type = vValue.typeId();
129 #endif
130  switch( type )
131  {
132  case QMetaType::QVariantList: RenderList ( vValue.toList() ); break;
133  case QMetaType::QStringList: RenderStringList( vValue.toStringList() ); break;
134  case QMetaType::QVariantMap: RenderMap ( vValue.toMap() ); break;
135  case QMetaType::QDateTime:
136  {
137  m_stream << "\"" << Encode(
138  MythDate::toString( vValue.toDateTime(), MythDate::ISODate ) )
139  << "\"";
140  break;
141  }
142  default:
143  {
144  m_stream << "\"" << Encode( vValue.toString() ) << "\"";
145  break;
146  }
147  }
148 }
149 
151 //
153 
154 void JSONSerializer::RenderList( const QVariantList &list )
155 {
156  bool bFirst = true;
157 
158  m_stream << "[";
159 
160  QListIterator< QVariant > it( list );
161 
162  while (it.hasNext())
163  {
164  if (bFirst)
165  bFirst = false;
166  else
167  m_stream << ",";
168 
169  RenderValue( it.next() );
170  }
171 
172  m_stream << "]";
173 }
174 
176 //
178 
179 void JSONSerializer::RenderStringList( const QStringList &list )
180 {
181  bool bFirst = true;
182 
183  m_stream << "[";
184 
185  QListIterator< QString > it( list );
186 
187  while (it.hasNext())
188  {
189  if (bFirst)
190  bFirst = false;
191  else
192  m_stream << ",";
193 
194  m_stream << "\"" << Encode( it.next() ) << "\"";
195  }
196 
197  m_stream << "]";
198 }
199 
201 //
203 
204 void JSONSerializer::RenderMap( const QVariantMap &map )
205 {
206  bool bFirst = true;
207 
208  m_stream << "{";
209 
210  QMapIterator< QString, QVariant > it( map );
211 
212  while (it.hasNext())
213  {
214  it.next();
215 
216  if (bFirst)
217  bFirst = false;
218  else
219  m_stream << ",";
220 
221  m_stream << "\"" << it.key() << "\":";
222  m_stream << "\"" << Encode( it.value().toString() ) << "\"";
223  }
224 
225  m_stream << "}";
226 }
227 
229 //
231 
232 QString JSONSerializer::Encode(const QString &sIn)
233 {
234  if (sIn.isEmpty())
235  return sIn;
236 
237  QString sStr = sIn;
238 
239  sStr.replace( '\\', "\\\\" ); // This must be first
240  sStr.replace( '"' , "\\\"" );
241  sStr.replace( '\b', "\\b" ); // ^H (\u0008)
242  sStr.replace( '\f', "\\f" ); // ^L (\u000C)
243  sStr.replace( '\n', "\\n" ); // ^J (\u000A)
244  sStr.replace( "\r", "\\r" ); // ^M (\u000D)
245  sStr.replace( "\t", "\\t" ); // ^I (\u0009)
246  sStr.replace( "/", "\\/" );
247 
248  // Escape remaining chars from \u0000 - \u001F
249  // Details at https://en.wikipedia.org/wiki/C0_and_C1_control_codes
250  sStr.replace(QChar('\u0000'), "\\u0000"); // ^@ NULL
251  sStr.replace(QChar('\u0001'), "\\u0001"); // ^A
252  sStr.replace(QChar('\u0002'), "\\u0002"); // ^B
253  sStr.replace(QChar('\u0003'), "\\u0003"); // ^C
254  sStr.replace(QChar('\u0004'), "\\u0004"); // ^D
255  sStr.replace(QChar('\u0005'), "\\u0005"); // ^E
256  sStr.replace(QChar('\u0006'), "\\u0006"); // ^F
257  sStr.replace(QChar('\u0007'), "\\u0007"); // ^G (\a)
258  sStr.replace(QChar('\u000B'), "\\u000B"); // ^K (\v)
259  sStr.replace(QChar('\u000E'), "\\u000E"); // ^N
260  sStr.replace(QChar('\u000F'), "\\u000F"); // ^O
261  sStr.replace(QChar('\u0010'), "\\u0010"); // ^P
262  sStr.replace(QChar('\u0011'), "\\u0011"); // ^Q XON
263  sStr.replace(QChar('\u0012'), "\\u0012"); // ^R
264  sStr.replace(QChar('\u0013'), "\\u0013"); // ^S XOFF
265  sStr.replace(QChar('\u0014'), "\\u0014"); // ^T
266  sStr.replace(QChar('\u0015'), "\\u0015"); // ^U
267  sStr.replace(QChar('\u0016'), "\\u0016"); // ^V
268  sStr.replace(QChar('\u0017'), "\\u0017"); // ^W
269  sStr.replace(QChar('\u0018'), "\\u0018"); // ^X
270  sStr.replace(QChar('\u0019'), "\\u0019"); // ^Y
271  sStr.replace(QChar('\u001A'), "\\u001A"); // ^Z
272  sStr.replace(QChar('\u001B'), "\\u001B");
273  sStr.replace(QChar('\u001C'), "\\u001C");
274  sStr.replace(QChar('\u001D'), "\\u001D");
275  sStr.replace(QChar('\u001E'), "\\u001E");
276  sStr.replace(QChar('\u001F'), "\\u001F");
277 
278  return sStr;
279 }
jsonSerializer.h
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:84
JSONSerializer::Encode
static QString Encode(const QString &sIn)
Definition: jsonSerializer.cpp:232
JSONSerializer::RenderList
void RenderList(const QVariantList &list)
Definition: jsonSerializer.cpp:154
JSONSerializer::GetContentType
QString GetContentType() override
Definition: jsonSerializer.cpp:22
JSONSerializer::EndObject
void EndObject(const QString &sName, const QObject *pObject) override
Definition: jsonSerializer.cpp:68
mythdate.h
JSONSerializer::m_bCommaNeeded
bool m_bCommaNeeded
Definition: jsonSerializer.h:37
Serializer::SerializeObjectProperties
void SerializeObjectProperties(const QObject *pObject)
Definition: serializer.cpp:103
JSONSerializer::RenderMap
void RenderMap(const QVariantMap &map)
Definition: jsonSerializer.cpp:204
JSONSerializer::BeginSerialize
void BeginSerialize(QString &sName) override
Definition: jsonSerializer.cpp:32
JSONSerializer::RenderStringList
void RenderStringList(const QStringList &list)
Definition: jsonSerializer.cpp:179
JSONSerializer::BeginObject
void BeginObject(const QString &sName, const QObject *pObject) override
Definition: jsonSerializer.cpp:57
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
JSONSerializer::EndSerialize
void EndSerialize() override
Definition: jsonSerializer.cpp:43
JSONSerializer::AddProperty
void AddProperty(const QString &sName, const QVariant &vValue, const QMetaObject *pMetaParent, const QMetaProperty *pMetaProp) override
Definition: jsonSerializer.cpp:79
JSONSerializer::RenderValue
void RenderValue(const QVariant &vValue)
Definition: jsonSerializer.cpp:98
JSONSerializer::m_stream
QTextStream m_stream
Definition: jsonSerializer.h:36