/* * Sailfin: a Jellyfin client written using Qt * Copyright (C) 2021 Chris Josten and the Sailfin Contributors. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "JellyfinQt/support/jsonconvimpl.h" #include "JellyfinQt/support/parseexception.h" #include namespace Jellyfin { namespace Support { QString uuidToString(const QUuid &source) { QString str = source.toString(); // Convert {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} (length: 38) // to xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (lenght: 32) return QString(str.mid(1, 8) + str.mid(10, 4) + str.mid(15, 4) + str.mid(20, 4) + str.mid(25 + 12)); } QUuid stringToUuid(const QString &source) { if (source.size() != 32) throw ParseException("Error while trying to parse JSON value as QUid: invalid length"); // Convert xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (length: 32) // to {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} (length: 38) QString qtParseableString; qtParseableString.reserve(38); qtParseableString += QStringLiteral("{") + source.mid(0, 8) + QStringLiteral("-") + source.mid(8, 4) + QStringLiteral("-") + source.mid(12, 4) + QStringLiteral("-") + source.mid(16, 4) + QStringLiteral("-") + source.mid(20, 12) + QStringLiteral("}"); return QUuid(qtParseableString); } // Trivial converters for built-in classes and simple types // int template <> int fromJsonValue(const QJsonValue &source, convertType) { if (!source.isDouble()) throw ParseException("Error while trying to parse JSON value as integer: not an integer"); return source.toInt(); } template <> QJsonValue toJsonValue(const int &source, convertType) { return QJsonValue(source); } // "long" template <> qint64 fromJsonValue(const QJsonValue &source, convertType) { if (!source.isDouble()) throw ParseException("Error while trying to parse JSON value as integer: not an integer"); return static_cast(source.toDouble()); } template <> QJsonValue toJsonValue(const qint64 &source, convertType) { return QJsonValue(static_cast(source)); } // bool template <> bool fromJsonValue(const QJsonValue &source, convertType) { if (!source.isBool()) throw ParseException("Error while trying to parse JSON value as boolean: not a boolean"); return source.toBool(); } template <> QJsonValue toJsonValue(const bool &source, convertType) { return QJsonValue(source); } // QString template <> QString fromJsonValue(const QJsonValue &source, convertType) { if (source.isNull()) { return QString(); } if (!source.isString()) { throw ParseException(QStringLiteral("Error while trying to parse JSON value %1 as string: not a string").arg(source.type())); } return source.toString(); } template <> QJsonValue toJsonValue(const QString &source, convertType) { return QJsonValue(source); } // QStringList template <> QStringList fromJsonValue(const QJsonValue &source, convertType) { switch(source.type()) { case QJsonValue::Array: { QJsonArray arr = source.toArray(); QStringList result; result.reserve(arr.size()); for(int i = 0; i < arr.size(); i++) { result.append(fromJsonValue(arr.at(i))); } return result; } case QJsonValue::Null: return QStringList(); default: throw ParseException(QStringLiteral("Error while trying to parse JSON value %1 as stringlist: not a list of strings").arg(source.type())); } } template <> QJsonValue toJsonValue(const QStringList &source, convertType) { QJsonArray result; for (int i = 0; i < source.size(); i++) { result.append(source[i]); } return result; } // QJsonObject template <> QJsonObject fromJsonValue(const QJsonValue &source, convertType) { switch(source.type()) { case QJsonValue::Null: return QJsonObject(); case QJsonValue::Object: return source.toObject(); default: throw ParseException("Error parsing JSON value as object: not an object"); } } template <> QJsonValue toJsonValue(const QJsonObject &source, convertType) { return QJsonValue(source); } // Double template <> double fromJsonValue(const QJsonValue &source, convertType) { if (!source.isDouble()) throw ParseException("Error parsing JSON value as double: not a double"); return source.toDouble(); } template <> QJsonValue toJsonValue(const double &source, convertType) { return QJsonValue(source); } // Float template <> float fromJsonValue(const QJsonValue &source, convertType) { if (!source.isDouble()) throw ParseException("Error parsing JSON value as float: not a double"); return static_cast(source.toDouble()); } template <> QJsonValue toJsonValue(const float &source, convertType) { return QJsonValue(static_cast(source)); } // QDateTime template <> QDateTime fromJsonValue(const QJsonValue &source, convertType) { switch (source.type()) { case QJsonValue::Null: return QDateTime(); case QJsonValue::String: // 2005-02-21T00:00:00.0000000Z return QDateTime::fromString(source.toString(), Qt::ISODate); default: throw ParseException("Error while trying to parse JSON value as DateTime: not a string"); } } template <> QJsonValue toJsonValue(const QDateTime &source, convertType) { return QJsonValue(source.toString(Qt::ISODate)); } // QVariant template <> QVariant fromJsonValue(const QJsonValue &source, convertType) { return source.toVariant(); } template<> QJsonValue toJsonValue(const QVariant &source, convertType) { return QJsonValue::fromVariant(source); } // QUuid template <> QUuid fromJsonValue(const QJsonValue &source, convertType) { if (!source.isString()) { qCritical() << "JSON Value " << source << "is not a string"; throw ParseException(QStringLiteral("Error while trying to parse JSON value as QUuid: not a string")); } return stringToUuid(source.toString()); } template <> QJsonValue toJsonValue(const QUuid &source, convertType) { return uuidToString(source); } // String types template <> QString toString(const QUuid &source, convertType) { return uuidToString(source); } template <> QString toString(const qint32 &source, convertType) { return QString::number(source); } template <> QString toString(const qint64 &source, convertType) { return QString::number(source); } template <> QString toString(const float &source, convertType) { return QString::number(source); } template <> QString toString(const double &source, convertType) { return QString::number(source); } template <> QString toString(const bool &source, convertType) { return source ? QStringLiteral("true") : QStringLiteral("false"); } template <> QString toString(const QString &source, convertType) { return source; } } // NS Support } // NS Jellyfin