Skip to content

Commit 35e9f16

Browse files
committed
Implement "invalid" fields handling in json serializer
- Add null value handling for all basic types - Add Infinity, -Inifinity and NaN values handling for float/double types - Add default value assignment for enum types - Update tests Fixes: #106
1 parent 784680f commit 35e9f16

File tree

3 files changed

+272
-31
lines changed

3 files changed

+272
-31
lines changed

3rdparty/microjson

src/protobuf/qprotobufjsonserializer.cpp

Lines changed: 102 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class QProtobufJsonSerializerPrivate final
4242
Q_DISABLE_COPY_MOVE(QProtobufJsonSerializerPrivate)
4343
public:
4444
using Serializer = std::function<QByteArray(const QVariant&)>;
45-
using Deserializer = std::function<QVariant(QByteArray)>;
45+
using Deserializer = std::function<QVariant(QByteArray, microjson::JsonType, bool &)>;
4646

4747
struct SerializationHandlers {
4848
Serializer serializer; /*!< serializer assigned to class */
@@ -194,44 +194,88 @@ class QProtobufJsonSerializerPrivate final
194194
return result;
195195
}
196196

197-
static QVariant deserializeInt32(const QByteArray &data) {
198-
return QVariant::fromValue(data.toInt());
197+
static QVariant deserializeInt32(const QByteArray &data, microjson::JsonType type, bool &ok) {
198+
auto val = data.toInt(&ok);
199+
ok |= type == microjson::JsonNumberType;
200+
return QVariant::fromValue(val);
199201
}
200202

201-
static QVariant deserializeUInt32(const QByteArray &data) {
202-
return QVariant::fromValue(data.toUInt());
203+
static QVariant deserializeUInt32(const QByteArray &data, microjson::JsonType type, bool &ok) {
204+
auto val = data.toUInt(&ok);
205+
ok |= type == microjson::JsonNumberType;
206+
return QVariant::fromValue(val);
203207
}
204208

205-
static QVariant deserializeInt64(const QByteArray &data) {
206-
return QVariant::fromValue(data.toLongLong());
209+
static QVariant deserializeInt64(const QByteArray &data, microjson::JsonType type, bool &ok) {
210+
auto val = data.toLongLong(&ok);
211+
ok |= type == microjson::JsonNumberType;
212+
return QVariant::fromValue(val);
207213
}
208214

209-
static QVariant deserializeUInt64(const QByteArray &data) {
210-
return QVariant::fromValue(data.toULongLong());
215+
static QVariant deserializeUInt64(const QByteArray &data, microjson::JsonType type, bool &ok) {
216+
auto val = data.toULongLong(&ok);
217+
ok |= type == microjson::JsonNumberType;
218+
return QVariant::fromValue(val);
211219
}
212220

213-
static QVariant deserializeFloat(const QByteArray &data) {
214-
return QVariant::fromValue(data.toFloat());
221+
static QVariant deserializeFloat(const QByteArray &data, microjson::JsonType type, bool &ok) {
222+
if (data == "NaN" || data == "Infinity" || data == "-Infinity") {
223+
ok = true;
224+
return QVariant();
225+
}
226+
auto val = data.toFloat(&ok);
227+
ok |= type == microjson::JsonNumberType;
228+
return QVariant::fromValue(val);
215229
}
216230

217-
static QVariant deserializeDouble(const QByteArray &data) {
218-
return QVariant::fromValue(data.toDouble());
231+
static QVariant deserializeDouble(const QByteArray &data, microjson::JsonType type, bool &ok) {
232+
if (data == "NaN" || data == "Infinity" || data == "-Infinity") {
233+
ok = true;
234+
return QVariant();
235+
}
236+
auto val = data.toDouble(&ok);
237+
ok |= type == microjson::JsonNumberType;
238+
return QVariant::fromValue(val);
219239
}
220240

221-
static QVariant deserializeBool(const QByteArray &data) {
222-
return QVariant::fromValue(QString::fromUtf8(data));
241+
static QVariant deserializeBool(const QByteArray &data, microjson::JsonType type, bool &ok) {
242+
if (type == microjson::JsonBoolType) {
243+
ok = true;
244+
return QVariant::fromValue(data == "true");
245+
}
246+
247+
ok = false;
248+
return QVariant();
223249
}
224250

225-
static QVariant deserializeString(const QByteArray &data) {
226-
return QVariant::fromValue(QString::fromUtf8(data).replace("\\\"", "\""));
251+
static QVariant deserializeString(const QByteArray &data, microjson::JsonType type, bool &ok) {
252+
if (type == microjson::JsonStringType) {
253+
ok = true;
254+
return QVariant::fromValue(QString::fromUtf8(data).replace("\\\"", "\""));
255+
}
256+
257+
ok = false;
258+
return QVariant();
227259
}
228260

229-
static QVariant deserializeByteArray(const QByteArray &data) {
230-
return QVariant::fromValue(QByteArray::fromBase64(data));
261+
static QVariant deserializeByteArray(const QByteArray &data, microjson::JsonType type, bool &ok) {
262+
if (type == microjson::JsonStringType) {
263+
ok = true;
264+
return QVariant::fromValue(QByteArray::fromBase64(data));
265+
}
266+
267+
ok = false;
268+
return QVariant();
231269
}
232270

233271
template<typename T>
234-
static QVariant deserializeList(const QByteArray &data) {
272+
static QVariant deserializeList(const QByteArray &data, microjson::JsonType type, bool &ok) {
273+
if (type != microjson::JsonArrayType) {
274+
ok = false;
275+
return QVariant();
276+
}
277+
278+
ok = true;
235279
QList<T> list;
236280
auto arrayValues = microjson::parseJsonArray(data.data(), static_cast<size_t>(data.size()));
237281
auto handler = handlers.find(qMetaTypeId<T>());
@@ -241,37 +285,46 @@ class QProtobufJsonSerializerPrivate final
241285
}
242286

243287
for (auto &arrayValue : arrayValues) {
244-
QVariant newValue = handler->second.deserializer(QByteArray::fromStdString(arrayValue.value));
288+
bool valueOk = false;
289+
QVariant newValue = handler->second.deserializer(QByteArray::fromStdString(arrayValue.value), arrayValue.type, valueOk);
245290
list.append(newValue.value<T>());
246291
}
247292
return QVariant::fromValue(list);
248293
}
249294

250-
static QVariant deserializeStringList(const QByteArray &data) {
295+
static QVariant deserializeStringList(const QByteArray &data, microjson::JsonType type, bool &ok) {
296+
if (type != microjson::JsonArrayType) {
297+
ok = false;
298+
return QVariant();
299+
}
300+
301+
ok = true;
251302
QStringList list;
252303
auto arrayValues = microjson::parseJsonArray(data.data(), static_cast<size_t>(data.size()));
253304
for (auto &arrayValue : arrayValues) {
254-
QVariant newValue = deserializeString(QByteArray::fromStdString(arrayValue.value));
305+
bool valueOk = false;
306+
QVariant newValue = deserializeString(QByteArray::fromStdString(arrayValue.value), arrayValue.type, valueOk);
255307
list.append(newValue.value<QString>());
256308
}
257309
return QVariant::fromValue(list);
258310
}
259311

260-
QVariant deserializeValue(int type, const QByteArray &data, microjson::JsonType jsonType) {
312+
QVariant deserializeValue(int type, const QByteArray &data, microjson::JsonType jsonType, bool &ok) {
261313
QVariant newValue;
262314
auto &handler = QtProtobufPrivate::findHandler(type);
263315
if (handler.deserializer) {
264316
QtProtobuf::QProtobufSelfcheckIterator it(data);
265317
QtProtobuf::QProtobufSelfcheckIterator last = it;
266318
last += it.size();
267319
while(it != last) {
320+
ok = true;
268321
handler.deserializer(qPtr, it, newValue);
269322
qDebug() << "newValue" << newValue;
270323
}
271324
} else {
272325
auto handler = handlers.find(type);
273326
if (handler != handlers.end() && handler->second.deserializer) {
274-
newValue = handler->second.deserializer(data);
327+
newValue = handler->second.deserializer(data, jsonType, ok);
275328
}
276329
}
277330
return newValue;
@@ -286,8 +339,16 @@ class QProtobufJsonSerializerPrivate final
286339
if (propertyIndex >= 0) {
287340
QMetaProperty metaProperty = metaObject.staticMetaObject.property(propertyIndex);
288341
auto userType = metaProperty.userType();
289-
QByteArray value = QByteArray::fromStdString(property.second.value);
290-
object->setProperty(name.c_str(), deserializeValue(userType, value, property.second.type));
342+
QByteArray rawValue = QByteArray::fromStdString(property.second.value);
343+
if (rawValue == "null" && property.second.type == microjson::JsonObjectType) {
344+
object->setProperty(name.c_str(), QVariant());//Initialize with default value
345+
return;
346+
}
347+
bool ok = false;
348+
QVariant value = deserializeValue(userType, rawValue, property.second.type, ok);
349+
if (ok) {
350+
object->setProperty(name.c_str(), value);
351+
}
291352
}
292353
}
293354
}
@@ -392,8 +453,15 @@ bool QProtobufJsonSerializer::deserializeMapPair(QVariant &key, QVariant &value,
392453
size_t i = 0;
393454
microjson::JsonProperty property;
394455
if (microjson::extractProperty(it.data(), static_cast<size_t>(it.size()), i, '}', property)) {
395-
key = dPtr->deserializeValue(key.userType(), QByteArray(it.data() + property.nameBegin, property.nameSize()), microjson::JsonStringType);
396-
value = dPtr->deserializeValue(value.userType(), QByteArray(it.data() + property.valueBegin, property.valueSize()), property.type);
456+
bool ok = false;
457+
key = dPtr->deserializeValue(key.userType(), QByteArray(it.data() + property.nameBegin, property.nameSize()), microjson::JsonStringType, ok);
458+
if (!ok) {
459+
key = QVariant();
460+
}
461+
value = dPtr->deserializeValue(value.userType(), QByteArray(it.data() + property.valueBegin, property.valueSize()), property.type, ok);
462+
if (!ok) {
463+
value = QVariant();
464+
}
397465
} else {
398466
it += it.size();
399467
return false;
@@ -433,7 +501,11 @@ void QProtobufJsonSerializer::deserializeEnumList(QList<int64> &value, const QMe
433501
auto arrayValues = microjson::parseJsonArray(it.data(), static_cast<size_t>(it.size()));
434502

435503
for (auto &arrayValue : arrayValues) {
436-
value.append(metaEnum.keyToValue(arrayValue.value.c_str()));
504+
if (arrayValue.value == "null") {
505+
value.append(metaEnum.value(0));
506+
} else {
507+
value.append(metaEnum.keyToValue(arrayValue.value.c_str()));
508+
}
437509
}
438510

439511
it += it.size();

0 commit comments

Comments
 (0)