序列化 JSON 数据 Qt
Posted
技术标签:
【中文标题】序列化 JSON 数据 Qt【英文标题】:Serializing JSON data Qt 【发布时间】:2013-01-21 20:37:14 【问题描述】:我正在使用 Qt 并尝试获取以下内容并将其转换为 JSON 文本,但是当我尝试编译它时,我得到一个符号未找到架构错误。
我目前正在使用内置的 Qt Json 库,因为我不知道如何让 QJson 工作并静态编译到代码中,这样就没有依赖关系了。
// Create the message body
QVariantMap message;
message.insert("date", QDate::currentDate().toString());
message.insert("eventType", eventName);
message.insert("payload", messagePayload);
// Initialize the Serializer
QJson::Serializer serializer;
bool ok;
// Serialize the data
QByteArray json = serializer.serialize(message, &ok);
编译器输出如下:
Undefined symbols for architecture x86_64:
"QJson::Serializer::serialize(QVariant const&, bool*)", referenced from:
SWebsocketClient::sendMessage(QString, QMap<QString, QVariant>) in swebsocketclient.o
这种方法是正确的,还是有更好的方法?我知道这个问题已经在其他地方被问过,但是其他答案中链接的大多数文章已经不存在了。
【问题讨论】:
顺便说一句,QJson 库似乎不是为该架构构建的。 您是如何获得/构建 Qjson 的?你如何链接它?显示您的 .pro 文件。 @FrankOsterfeld 我没有做任何事情来构建/获得 QJson。我尝试在我的 Mac 上通过自制软件安装它,然后将“QT += sql qjson”添加到我的 .pro 文件中,但我认为 Qt 内置了一些 JSON 支持?如果没有,如果我安装它,我如何在我的项目中使用 QJson 查看自制软件? 如果它是内置的,就不需要 qjson(Json 支持是 Qt5 的一部分,但不是 Qt4 的一部分)。为了使 CONFIG += qjson (CONFIG, not QT) 工作,qjson 需要安装一个 .prf 文件,我在 repo 中没有看到。 (它使用 CMake 使这些事情变得更容易)。所以我假设你需要手动执行 LIBS += -lqjson @FrankOsterfeld 成功了!谢谢!我不知道您是否想将其发布为答案,或者我是否应该继续回答我自己的问题。但我认为你应该接受这个功劳。 【参考方案1】:您始终可以改用这个 JSON 库:
/*
* qvjson.h
*
* Created on: Apr 23, 2010
* Author: drh
*/
#ifndef QVJSON_H_
#define QVJSON_H_
#include <QMap>
#include <QList>
#include <QVariant>
#include <QRegExp>
class QvJson
public:
QvJson();
virtual ~QvJson();
QVariant parseJson(const QString& jsonString);
// The jsonObject is a QVariant that may be a --
// -- QMap<QString, QVariant>
// -- QList<QVariant>
// -- QString
// -- integer
// -- real number
// -- bool
// -- null (implemented as a QVariant() object)
// Where QVariant appears in the above list, it may recursively
// be one of the above.
QString encodeJson(const QVariant& jsonObject);
private:
enum Error
ErrorUnrecognizedToken,
ErrorMustBeString,
ErrorMissingColon,
ErrorMissingCommaOrClose,
ErrorNoClosingQuote,
ErrorEndOfInput,
ErrorInvalidNumericValue,
ErrorInvalidHexValue,
ErrorUnrecognizedObject
;
QRegExp mNonBlank;
QRegExp mFindQuote;
QString nextToken(const QString& jsonString, int& position);
QString peekToken(const QString& jsonString, int position);
QVariant parseInternal(const QString& jsonString, int& position, int nesting);
QVariant parseObject(const QString& jsonString, int& position, int nesting);
QVariant parseArray(const QString& jsonString, int& position, int nesting);
QVariant parseString(const QString& jsonString, int& position, int nesting);
QVariant parseBool(const QString& jsonString, int& position, int nesting);
QVariant parseNull(const QString& jsonString, int& position, int nesting);
QVariant parseNumber(const QString& jsonString, int& position, int nesting);
QVariant syntaxError(const QString& method, const QString& jsonString, int position, int nesting, Error error);
QString encodeObject(const QVariant& jsonObject);
QString encodeArray(const QVariant& jsonObject);
QString encodeString(const QVariant& jsonObject);
QString encodeString(const QString& value);
QString encodeNumeric(const QVariant& jsonObject);
QString encodeBool(const QVariant& jsonObject);
QString encodeNull(const QVariant& jsonObject);
QString encodingError(const QString& method, const QVariant& jsonObject, Error error);
;
#endif /* QVJSON_H_ */
/*
* qvjson.cpp
*
* Created on: Apr 23, 2010
* Author: drh
*/
#include "qvjson.h"
#include <QStringList>
#include <QMessageBox>
QvJson::QvJson()
mNonBlank = QRegExp("\\S", Qt::CaseSensitive, QRegExp::RegExp);
mFindQuote = QRegExp("[^\\\\]\"", Qt::CaseSensitive, QRegExp::RegExp);
QvJson::~QvJson()
// TODO Auto-generated destructor stub
QVariant QvJson::parseJson(const QString& jsonString)
int position = 0;
QVariant result;
result = parseInternal(jsonString, position, 0);
if (result.type() == QVariant::StringList)
QMessageBox::critical(NULL, "", result.toString());
QString token(nextToken(jsonString, position));
if (!token.isEmpty())
QMessageBox::critical(NULL, "", QObject::tr("Invalid JSON string -- remaining token %1 at position %2.").arg(token).arg(position));
return result;
QString QvJson::nextToken(const QString& jsonString, int& position)
if (position >= jsonString.count())
return QString();
while (jsonString.at(position) == ' ')
position++;
if (position >= jsonString.count())
return QString();
if (jsonString.at(position).isLetter())
if (position + 4 < jsonString.count())
QString word = jsonString.mid(position, 4);
if ((word == "true") || (word == "null"))
position += 4;
while (position < jsonString.count() && jsonString.at(position) == ' ')
position++;
return word;
if ((word == "fals") && (position + 5 < jsonString.count()) && jsonString.at(position + 4) == 'e')
position += 5;
while (position < jsonString.count() && jsonString.at(position) == ' ')
position++;
return "false";
QString result = QString(jsonString.at(position));
position++;
while (position < jsonString.count() && jsonString.at(position) == ' ')
position++;
return result;
// By virtue of its non-& position parm, this method "peeks" at the token without consuming it.
QString QvJson::peekToken(const QString& jsonString, int position)
return (nextToken(jsonString, position));
QVariant QvJson::parseInternal(const QString& jsonString, int& position, int nesting)
QString token(peekToken(jsonString, position));
QVariant result;
int startPosition = position; // For debug
Q_UNUSED(startPosition);
if (token.isNull())
result = syntaxError("parseInternal", jsonString, position, nesting + 1, ErrorEndOfInput);
else if (token == "")
result = parseObject(jsonString, position, nesting + 1);
else if (token == "[")
result = parseArray(jsonString, position, nesting + 1);
else if (token == "\"")
result = parseString(jsonString, position, nesting + 1);
else if ((token == "true") || (token == "false"))
result = parseBool(jsonString, position, nesting + 1);
else if (token == "null")
result = parseNull(jsonString, position, nesting + 1);
else if ((token == "-") || (token.at(0).isDigit()))
result = parseNumber(jsonString, position, nesting + 1);
else
result = syntaxError("parseInternal", jsonString, position, nesting + 1, ErrorUnrecognizedToken);
return result;
QVariant QvJson::parseObject(const QString& jsonString, int& position, int nesting)
QMap<QString, QVariant> resultObject;
QString token;
int startPosition = position; // For debug
Q_UNUSED(startPosition);
token = nextToken(jsonString, position);
Q_ASSERT(token == "");
// Handle case of empty object
token = peekToken(jsonString, position);
if (token == '')
return QVariant(resultObject);
do
// Next item must be a string
token = peekToken(jsonString, position);
if (token != "\"")
return syntaxError("parseObject", jsonString, position, nesting + 1, ErrorMustBeString);
QVariant propName;
propName = parseString(jsonString, position, nesting + 1);
// Check for error
if (propName.type() == QVariant::StringList)
QStringList propNameError(propName.toStringList());
propNameError << QObject::tr("in parseObject(%1,%2)").arg(position).arg(nesting);
return QVariant(propNameError);
// Expect a ":"
token = nextToken(jsonString, position);
if (token != ":")
return syntaxError("parseObject", jsonString, position, nesting + 1, ErrorMissingColon);
// Now get the value
QVariant propValue;
propValue = parseInternal(jsonString, position, nesting + 1);
// Check for error
if (propValue.type() == QVariant::StringList)
QStringList propValueError(propValue.toStringList());
propValueError << QObject::tr("in parseObject(%1,%2)").arg(position).arg(nesting);
return QVariant(propValueError);
resultObject[propName.toString()] = propValue;
// Next token must be a "," or ""
token = nextToken(jsonString, position);
if (token == "")
return QVariant(resultObject);
else if (token != ",")
return syntaxError("parseObject", jsonString, position, nesting + 1, ErrorMissingCommaOrClose);
while (true);
QVariant QvJson::parseArray(const QString& jsonString, int& position, int nesting)
QList<QVariant> resultArray;
QString token;
token = nextToken(jsonString, position);
Q_ASSERT(token == "[");
// Handle case of empty object
token = peekToken(jsonString, position);
if (token == ']')
return QVariant(resultArray);
do
// Get the element of the array
QVariant propValue;
propValue = parseInternal(jsonString, position, nesting + 1);
// Check for error
if (propValue.type() == QVariant::StringList)
QStringList propValueError(propValue.toStringList());
propValueError << QObject::tr("in parseObject(%1,%2)").arg(position).arg(nesting);
return QVariant(propValueError);
resultArray << propValue;
// Next token must be a "," or "]"
token = nextToken(jsonString, position);
if (token == "]")
return QVariant(resultArray);
else if (token != ",")
return syntaxError("parseArray", jsonString, position, nesting + 1, ErrorMissingCommaOrClose);
while (true);
QVariant QvJson::parseString(const QString& jsonString, int& position, int nesting)
QString result;
// Skip over the double quote character
Q_ASSERT(jsonString.at(position) == '"');
position++;
do
if (position >= jsonString.count())
return syntaxError("parseString", jsonString, position, nesting, ErrorNoClosingQuote);
if (jsonString.at(position) == '"')
break;
if (jsonString.at(position) == '\\')
position++;
if (position >= jsonString.count())
return syntaxError("parseString", jsonString, position, nesting, ErrorNoClosingQuote);
switch (jsonString.at(position).unicode())
case 'b':
result.append('\b');
break;
case 'f':
result.append('\f');
break;
case 'n':
result.append('\n');
break;
case 'r':
result.append('\r');
break;
case 't':
result.append('\t');
break;
case 'u':
if (position + 4 >= jsonString.count())
return syntaxError("parseString", jsonString, position, nesting, ErrorNoClosingQuote);
QString hex = jsonString.mid(position + 1, 4);
bool ok;
int value = hex.toInt(&ok, 16);
if (!ok)
return syntaxError("parseString", jsonString, position+1, nesting, ErrorInvalidHexValue);
result.append(QChar(value));
position += 4;
default:
result.append(jsonString.at(position));
position++;
else
result.append(jsonString.at(position));
position++;
while(true);
Q_ASSERT(jsonString.at(position) == '"');
position++;
return QVariant(result);
QVariant QvJson::parseBool(const QString& jsonString, int& position, int nesting)
bool resultBool;
QString token;
token = nextToken(jsonString, position);
if (token == "true")
resultBool = true;
else if (token == "false")
resultBool = false;
else
Q_ASSERT(false);
return QVariant(resultBool);
QVariant QvJson::parseNull(const QString& jsonString, int& position, int nesting)
QString token;
token = nextToken(jsonString, position);
Q_ASSERT(token == "null");
Q_UNUSED(token);
return QVariant();
QVariant QvJson::parseNumber(const QString& jsonString, int& position, int nesting)
int startPosition = position;
// Allow a leading minus sign
if (jsonString.at(position) == '-') position++;
if (position >= jsonString.count())
return syntaxError("parseNumber", jsonString, position, nesting + 1, ErrorEndOfInput);
// Allow one or more decimal digits
if (!jsonString.at(position).isDigit())
return syntaxError("parseNumber", jsonString, position, nesting + 1, ErrorInvalidNumericValue);
while (position < jsonString.count() && jsonString.at(position).isDigit())
position++;
if (position >= jsonString.count() ||
(jsonString.at(position) != '.' && jsonString.at(position) != 'e' && jsonString.at(position) != 'E'))
bool ok = false;
int resultInt = jsonString.mid(startPosition, position - startPosition).toInt(&ok);
if (!ok)
return syntaxError("parseNumber", jsonString, position, nesting + 1, ErrorInvalidNumericValue);
return QVariant(resultInt);
// Consume any fraction part
if (jsonString.at(position) == '.')
position++;
while (position < jsonString.count() && jsonString.at(position).isDigit())
position++;
// Consume any exponent part
if (jsonString.at(position) == 'e' || jsonString.at(position) == 'E')
position++;
// Consume +/- if present
if (jsonString.at(position) == '+' || jsonString.at(position) == '-')
position++;
// Must have at least one digit
if (!jsonString.at(position).isDigit())
return syntaxError("parseNumber", jsonString, position, nesting + 1, ErrorInvalidNumericValue);
while (position < jsonString.count() && jsonString.at(position).isDigit())
position++;
// Should have a valid floating point value at this point
bool ok = false;
qreal resultReal = jsonString.mid(startPosition, position - startPosition).toDouble(&ok);
if (!ok)
return syntaxError("parseNumber", jsonString, position, nesting + 1, ErrorInvalidNumericValue);
return QVariant(resultReal);
QVariant QvJson::syntaxError(const QString& method, const QString& jsonString, int position, int nesting, Error error)
QString text;
switch (error)
case ErrorInvalidNumericValue:
text = QObject::tr("Invalid numeric value");
break;
case ErrorInvalidHexValue:
text = QObject::tr("Invalid hex value");
break;
case ErrorEndOfInput:
text = QObject::tr("Unexpected end of input");
break;
case ErrorNoClosingQuote:
text = QObject::tr("No closing quote for literal string");
break;
case ErrorMissingColon:
text = QObject::tr("Missing ':' between attribute name and value");
break;
case ErrorMissingCommaOrClose:
text = QObject::tr("Missing comma, '', or ']'");
break;
case ErrorMustBeString:
text = QObject::tr("The name of an attribute must be a valid character string");
break;
case ErrorUnrecognizedToken:
text = QObject::tr("The token was not recognized");
break;
default:
Q_ASSERT(false);
QString errorMsg = QObject::tr("*** Error %1 in QvJson::%2 at position %3 -- %4").arg(error).arg(method).arg(position).arg(text);
QStringList errorList;
errorList << errorMsg;
return QVariant(errorList);
QString QvJson::encodeJson(const QVariant& jsonObject)
QVariant::Type type = jsonObject.type();
switch (type)
case QVariant::Map:
return encodeObject(jsonObject);
case QVariant::List:
return encodeArray(jsonObject);
case QVariant::String:
return encodeString(jsonObject);
case QVariant::Int:
case QVariant::Double:
return encodeNumeric(jsonObject);
case QVariant::Bool:
return encodeBool(jsonObject);
case QVariant::Invalid:
return encodeNull(jsonObject);
default:
return encodingError("encodeJson", jsonObject, ErrorUnrecognizedObject);
QString QvJson::encodeObject(const QVariant& jsonObject)
QString result(" ");
QMap<QString, QVariant> map = jsonObject.toMap();
QMapIterator<QString, QVariant> i(map);
while (i.hasNext())
i.next();
result.append(encodeString(i.key()));
result.append(" : ");
result.append(encodeJson(i.value()));
if (i.hasNext())
result.append(", ");
result.append(" ");
return result;
QString QvJson::encodeArray(const QVariant& jsonObject)
QString result("[ ");
QList<QVariant> list = jsonObject.toList();
for (int i = 0; i < list.count(); i++)
result.append(encodeJson(list.at(i)));
if (i+1 < list.count())
result.append(", ");
result.append(" ]");
return result;
QString QvJson::encodeString(const QVariant &jsonObject)
return encodeString(jsonObject.toString());
QString QvJson::encodeString(const QString& value)
QString result = "\"";
for (int i = 0; i < value.count(); i++)
ushort chr = value.at(i).unicode();
if (chr < 32)
switch (chr)
case '\b':
result.append("\\b");
break;
case '\f':
result.append("\\f");
break;
case '\n':
result.append("\\n");
break;
case '\r':
result.append("\\r");
break;
case '\t':
result.append("\\t");
break;
default:
result.append("\\u");
result.append(QString::number(chr, 16).rightJustified(4, '0'));
// End switch
else if (chr > 255)
result.append("\\u");
result.append(QString::number(chr, 16).rightJustified(4, '0'));
else
result.append(value.at(i));
result.append('"');
QString displayResult = result; // For debug, since "result" often doesn't show
Q_UNUSED(displayResult);
return result;
QString QvJson::encodeNumeric(const QVariant& jsonObject)
return jsonObject.toString();
QString QvJson::encodeBool(const QVariant& jsonObject)
return jsonObject.toString();
QString QvJson::encodeNull(const QVariant& jsonObject)
return "null";
QString QvJson::encodingError(const QString& method, const QVariant& jsonObject, Error error)
QString text;
switch (error)
case ErrorUnrecognizedObject:
text = QObject::tr("Unrecognized object type");
break;
default:
Q_ASSERT(false);
return QObject::tr("*** Error %1 in QvJson::%2 -- %3").arg(error).arg(method).arg(text);
【讨论】:
不确定从网络复制/粘贴另一个 Qt json 实现(不包括单元测试)会提高可维护性。 @FrankOsterfeld - 不是来自网络。从我的私人藏匿处。以上是关于序列化 JSON 数据 Qt的主要内容,如果未能解决你的问题,请参考以下文章