Convert EntityTree direct to JSON, not via QJsonDocument

This commit is contained in:
Simon Walton 2018-10-11 18:13:26 -07:00
parent c938c595c0
commit 0eec0e376c
6 changed files with 141 additions and 1 deletions

View file

@ -35,6 +35,7 @@
#include "QVariantGLM.h"
#include "EntitiesLogging.h"
#include "RecurseOctreeToMapOperator.h"
#include "RecurseOctreeToJsonOperator.h"
#include "LogHandler.h"
#include "EntityEditFilters.h"
#include "EntityDynamicFactoryInterface.h"
@ -2658,6 +2659,17 @@ bool EntityTree::readFromMap(QVariantMap& map) {
return success;
}
bool EntityTree::writeToJSON(QString & jsonString, const OctreeElementPointer & element) {
QScriptEngine scriptEngine;
RecurseOctreeToJSONOperator theOperator(element, &scriptEngine, jsonString);
withReadLock([&] {
recurseTreeWithOperator(&theOperator);
});
jsonString = theOperator.getJson();
return true;
}
void EntityTree::resetClientEditStats() {
_treeResetTime = usecTimestampNow();
_maxEditDelta = 0;

View file

@ -224,6 +224,8 @@ public:
virtual bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues,
bool skipThoseWithBadParents) override;
virtual bool readFromMap(QVariantMap& entityDescription) override;
virtual bool writeToJSON(QString& jsonString, const OctreeElementPointer& element) override;
glm::vec3 getContentsDimensions();
float getContentsLargestDimension();

View file

@ -0,0 +1,45 @@
//
// RecurseOctreeToJSONOperator.cpp
// libraries/entities/src
//
// Created by Simon Walton on Oct 11, 2018.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "RecurseOctreeToJSONOperator.h"
#include "EntityItemProperties.h"
RecurseOctreeToJSONOperator::RecurseOctreeToJSONOperator(const OctreeElementPointer& top, QScriptEngine* engine,
QString jsonPrefix /* = QString() */)
: _top(top)
, _engine(engine)
, _json(jsonPrefix)
{
_toStringMethod = _engine->evaluate("(function() { return JSON.stringify(this, null, ' ') })");
}
bool RecurseOctreeToJSONOperator::postRecursion(const OctreeElementPointer& element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->forEachEntity([&](const EntityItemPointer& entity) { processEntity(entity); } );
return true;
}
void RecurseOctreeToJSONOperator::processEntity(const EntityItemPointer& entity) {
QScriptValue qScriptValues = EntityItemNonDefaultPropertiesToScriptValue(_engine, entity->getProperties());
if (comma) {
_json += ',';
};
comma = true;
_json += "\n ";
// Override default toString():
qScriptValues.setProperty("toString", _toStringMethod);
QString jsonResult = qScriptValues.toString();
//auto exceptionString2 = _engine->uncaughtException().toString();
_json += jsonResult;
}

View file

@ -0,0 +1,31 @@
//
// RecurseOctreeToJSONOperator.h
// libraries/entities/src
//
// Created by Simon Walton on Oct 11, 2018.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "EntityTree.h"
class RecurseOctreeToJSONOperator : public RecurseOctreeOperator {
public:
RecurseOctreeToJSONOperator(const OctreeElementPointer& top, QScriptEngine* engine, QString jsonPrefix = QString());
virtual bool preRecursion(const OctreeElementPointer& element) override { return true; };
virtual bool postRecursion(const OctreeElementPointer& element) override;
QString getJson() const { return _json; }
private:
void processEntity(const EntityItemPointer& entity);
const OctreeElementPointer& _top;
QScriptEngine* _engine;
QScriptValue _toStringMethod;
QString _json;
bool comma { false };
};

View file

@ -51,7 +51,6 @@
#include "OctreeQueryNode.h"
#include "OctreeUtils.h"
QVector<QString> PERSIST_EXTENSIONS = {"json", "json.gz"};
Octree::Octree(bool shouldReaverage) :
@ -892,13 +891,61 @@ bool Octree::toJSONDocument(QJsonDocument* doc, const OctreeElementPointer& elem
return true;
}
bool Octree::toJSONString(QString& jsonString, const OctreeElementPointer& element) {
OctreeElementPointer top;
if (element) {
top = element;
} else {
top = _rootElement;
}
jsonString += QString(R"({
"DataVersion": %1,
"Entities": [)").arg(_persistDataVersion);
writeToJSON(jsonString, top);
// include the "bitstream" version
PacketType expectedType = expectedDataPacketType();
PacketVersion expectedVersion = versionForPacketType(expectedType);
jsonString += QString(R"(
],
"Id": "%1",
"Version": %2
}
)").arg(_persistID.toString()).arg((int)expectedVersion);
return true;
}
bool Octree::toJSON(QByteArray* data, const OctreeElementPointer& element, bool doGzip) {
#define HIFI_USE_DIRECT_TO_JSON
#ifdef HIFI_USE_DIRECT_TO_JSON
QString jsonString;
toJSONString(jsonString);
if (doGzip) {
if (!gzip(jsonString.toUtf8(), *data, -1)) {
qCritical("Unable to gzip data while saving to json.");
return false;
}
} else {
*data = jsonString.toUtf8();
}
#else
QJsonDocument doc;
if (!toJSONDocument(&doc, element)) {
qCritical("Failed to convert Entities to JSON document.");
return false;
}
QString jsonString;
toJSONString(jsonString);
if (doGzip) {
QByteArray jsonData = doc.toJson();
@ -909,6 +956,7 @@ bool Octree::toJSON(QByteArray* data, const OctreeElementPointer& element, bool
} else {
*data = doc.toJson();
}
#endif // HIFI_USE_DIRECT_TO_JSON
return true;
}

View file

@ -202,11 +202,13 @@ public:
// Octree exporters
bool toJSONDocument(QJsonDocument* doc, const OctreeElementPointer& element = nullptr);
bool toJSONString(QString& jsonString, const OctreeElementPointer& element = nullptr);
bool toJSON(QByteArray* data, const OctreeElementPointer& element = nullptr, bool doGzip = false);
bool writeToFile(const char* filename, const OctreeElementPointer& element = nullptr, QString persistAsFileType = "json.gz");
bool writeToJSONFile(const char* filename, const OctreeElementPointer& element = nullptr, bool doGzip = false);
virtual bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues,
bool skipThoseWithBadParents) = 0;
virtual bool writeToJSON(QString& jsonString, const OctreeElementPointer& element) = 0;
// Octree importers
bool readFromFile(const char* filename);