This repository has been archived on 2025-12-24. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
yachat/third-party/JsonQt/lib/JsonRpc.cpp
2025-12-25 01:38:25 +05:00

167 lines
4.4 KiB
C++

#include "JsonRpc.h"
#include "JsonToVariant.h"
#include "VariantToJson.h"
#include <QDebug>
namespace JsonQt
{
JsonRpc::JsonRpc(QObject* parent) : QObject(parent) {}
void JsonRpc::sendRequest(const QVariant& id, const QString& method, const QVariant& parameters)
{
Q_ASSERT(parameters.type() == QVariant::List || parameters.type() == QVariant::Map || parameters.isNull());
QVariantMap request;
request["jsonrpc"] = "2.0";
request["method"] = method;
request["id"] = id;
if(!parameters.isNull())
{
request["params"] = parameters;
}
emit sendJson(VariantToJson::parse(request));
}
void JsonRpc::sendNotification(const QString& method, const QVariant& parameters)
{
Q_ASSERT(parameters.type() == QVariant::List || parameters.type() == QVariant::Map || parameters.isNull());
QVariantMap request;
request["jsonrpc"] = "2.0";
request["method"] = method;
// no ID for notifications.
if(!parameters.isNull())
{
request["params"] = parameters;
}
emit sendJson(VariantToJson::parse(request));
}
void JsonRpc::sendResponse(const QVariant& id, const QVariant& result)
{
QVariantMap response;
response["jsonrpc"] = "2.0";
response["id"] = id;
response["result"] = result;
emit sendJson(VariantToJson::parse(response));
}
void JsonRpc::sendError(const QVariant& id, int errorCode, const QString& message, const QVariant& data)
{
QVariantMap error;
error["code"] = errorCode;
error["message"] = message;
error["data"] = data;
QVariantMap response;
response["jsonrpc"] = "2.0";
response["id"] = id;
response["error"] = error;
emit sendJson(VariantToJson::parse(response));
}
void JsonRpc::processJson(const QString& json)
{
QList<QVariantMap> objects;
try
{
objects = JsonToVariant::multiParse(json);
}
catch(ParseException)
{
sendError(QVariant(), InvalidJson, "Parse error.");
return;
}
Q_FOREACH(const QVariantMap& object, objects)
{
if(object.value("jsonrpc").toString() != "2.0")
{
sendError(object.value("id"), InvalidJsonRpc, "JSON-RPC version not specified or not supported.", object);
continue;
}
// Notification or request
if(object.contains("method"))
{
if(object.value("method").type() != QVariant::String)
{
sendError(object.value("id"), InvalidJsonRpc, "'method' member of request must be a string.", object);
continue;
}
QString method = object.value("method").toString();
QVariant parameters = object.value("params");
if(parameters.isNull()) parameters = QVariantList();
if(parameters.type() != QVariant::List && parameters.type() != QVariant::Map)
{
sendError(object.value("id"), InvalidJsonRpc, "'parameters' member of request must be omitted, a list, or an object.", object);
continue;
}
// Request or notification
if(object.contains("id"))
{
emit requestReceived(object.value("id"), method, parameters);
}
else
{
emit notificationReceived(method, parameters);
}
continue;
}
// Request successful
if(object.contains("result"))
{
if(!object.contains("id"))
{
sendError(QVariant(), InvalidJsonRpc, "ID not specified in response.", object);
continue;
}
emit responseReceived(object.value("id"), object.value("result"));
continue;
}
// Request failed
if(object.contains("error"))
{
if(!object.contains("id"))
{
sendError(QVariant(), InvalidJsonRpc, "ID not specified in response.", object);
continue;
}
if(object.value("error").type() != QVariant::Map)
{
sendError(object.value("id"), InvalidJsonRpc, "'error' member is not an Error object.", object);
continue;
}
QVariantMap error = object.value("error").toMap();
if(error.value("code").type() != QVariant::Int)
{
sendError(object.value("id"), InvalidJsonRpc, "'code' member of error object is not an integer.", object);
continue;
}
if(error.value("message").type() != QVariant::String)
{
sendError(object.value("id"), InvalidJsonRpc, "'message' member of error object is not a string.", object);
continue;
}
emit errorReceived(object.value("id"), error.value("code").toInt(), error.value("message").toString(), error.value("data"));
continue;
}
// Not a notification, request, or response
sendError(object.value("id"), InvalidJsonRpc, "JSON object doesn't appear to be a JSON-RPC request, notification, or response.", object);
}
}
};