Skip to content

Instantly share code, notes, and snippets.

@jniemann66
Last active March 8, 2019 04:58
Show Gist options
  • Save jniemann66/d97999fea57879dbb9cebfc84e56da37 to your computer and use it in GitHub Desktop.
Save jniemann66/d97999fea57879dbb9cebfc84e56da37 to your computer and use it in GitHub Desktop.
Qt printJSON - format a QJsonValue into a string, and just report length of large strings or arrays
#include "printjson.h"
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
#include <QVariant>
#include <QTextStream>
#include <QRegularExpression>
QString sprintJson(const QJsonValue& jsonValue, int maxLength, int indentLevel) {
QString jsonString;
// jsonString.reserve(16384); // no observable benefit in tests
QTextStream out(&jsonString);
printJson(out, jsonValue, maxLength, indentLevel);
return jsonString;
}
// T is any type that has an operator<<(const QString&)
template <typename T>
void printJson(T& stream, const QJsonValue& jsonValue, int maxLength, int indentLevel) {
static const QString indent{QStringLiteral(" ")};
static const QString slashN{QStringLiteral("\n")};
static const QString commaSlashN{QStringLiteral(",\n")};
static const QString openBraceSlashN{QStringLiteral("{\n")};
static const QString openSquareSlashN{QStringLiteral("[\n")};
static const QString closeBrace{QStringLiteral("}")};
static const QString closeSquare{QStringLiteral("]")};
static const QString doubleQuote{QStringLiteral("\"")};
static const QString doubleQuoteColon{QStringLiteral("\": ")};
static const QString null{QStringLiteral("null")};
QString whiteSpace(indent.repeated(indentLevel));
switch(jsonValue.type()) {
case QJsonValue::Object:
{
stream << openBraceSlashN;
QJsonObject o = jsonValue.toObject();
const QStringList& keys = o.keys();
int lastIndex = keys.count() - 1;
for(int i = 0; i <= lastIndex; ++i) {
stream << whiteSpace << indent << doubleQuote << keys.at(i) << doubleQuoteColon;
printJson(stream, o.value(keys.at(i)), maxLength, indentLevel + 1);
stream << (Q_UNLIKELY(i == lastIndex) ? slashN : commaSlashN);
}
stream << whiteSpace << closeBrace;
return;
}
case QJsonValue::Array:
{
QString s;
QTextStream t(&s);
t << openSquareSlashN;
const QJsonArray a = jsonValue.toArray();
int lastIndex = a.count() - 1;
for(int i = 0; i <= lastIndex; ++i) {
t << whiteSpace << indent;
printJson(t, a.at(i), maxLength, indentLevel + 1);
t << (Q_UNLIKELY(i == lastIndex) ? slashN : commaSlashN);
}
t << whiteSpace << closeSquare;
if(Q_UNLIKELY(s.length() > maxLength)) { // summarize array
stream << QStringLiteral("\"[%1 elements, %2 chars]\"").arg(a.count()).arg(s.length());
} else { // print array
stream << s;
}
return;
}
case QJsonValue::String:
{
QString s = jsonValue.toVariant().toString();
if(Q_UNLIKELY(s.length() > maxLength)) {
stream << QStringLiteral("\"(%1 chars)\"").arg(s.length());
} else {
// check for control characters inside string using this regex : [\b\f\n\r\t\"\\]*
if(s.contains(QRegularExpression("[\\b\\f\\n\\r\\t\\\"\\\\]*"))) { // to-do: this is gonna be real slow. find an optimal solution
// escape the control characters inside the string
s.replace('\\', "\\\\")
.replace('\b', "\\b")
.replace('\f', "\\f")
.replace('\n', "\\n")
.replace('\r', "\\r")
.replace('\t', "\\t")
.replace('\"', "\\\"")
;
}
stream << doubleQuote << s << doubleQuote;
}
return;
}
case QJsonValue::Double:
case QJsonValue::Bool:
stream << jsonValue.toVariant().toString();
return;
case QJsonValue::Null:
case QJsonValue::Undefined:
stream << null;
}
}
#pragma once
// printjson.h : utility function for formatting JSON values (object or array) as a string,
// substituting a size summary for string values above a predetermined character length threshold
#include <QString>
#include <QJsonValue>
template <typename T>
void printJson(T &stream, const QJsonValue& jsonValue, int maxLength = 256, int indentLevel = 0);
QString sprintJson(const QJsonValue& json, int maxLength = 256, int indentLevel = 0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment