From 77b6a209abeafd059af2148b2eac12254841fa09 Mon Sep 17 00:00:00 2001
From: Andrzej Kapolka <drzej.k@gmail.com>
Date: Mon, 16 Jun 2014 14:51:22 -0700
Subject: [PATCH] More progress on json reading.

---
 libraries/metavoxels/src/Bitstream.cpp | 272 ++++++++++++++++++++++++-
 libraries/metavoxels/src/Bitstream.h   | 103 +++++++++-
 tools/mtc/src/main.cpp                 |  13 ++
 3 files changed, 379 insertions(+), 9 deletions(-)

diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp
index 91e2cd8723..8f880a1803 100644
--- a/libraries/metavoxels/src/Bitstream.cpp
+++ b/libraries/metavoxels/src/Bitstream.cpp
@@ -1825,6 +1825,10 @@ QJsonValue JSONWriter::getData(const QObject* object) {
     return streamer->getJSONData(*this, object);
 }
 
+QJsonValue JSONWriter::getData(const GenericValue& value) {
+    return value.getStreamer()->getJSONData(*this, value.getValue());
+}
+
 void JSONWriter::addTypeStreamer(const TypeStreamer* streamer) {
     if (!_typeStreamerNames.contains(streamer->getName())) {
         _typeStreamerNames.insert(streamer->getName());
@@ -1877,7 +1881,7 @@ QJsonDocument JSONWriter::getDocument() const {
     return QJsonDocument(top);
 }
 
-JSONReader::JSONReader(const QJsonDocument& document) {
+JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode genericsMode) {
     QJsonObject top = document.object();
     QJsonArray types = top.value("types").toArray();
     for (int i = types.size() - 1; i >= 0; i--) {
@@ -1918,6 +1922,155 @@ JSONReader::JSONReader(const QJsonDocument& document) {
         
     }
     
+    _contents = top.value("contents").toArray();
+    _contentsIterator = _contents.constBegin();
+}
+
+void JSONReader::putData(const QJsonValue& data, bool& value) {
+    value = data.toBool();
+}
+
+void JSONReader::putData(const QJsonValue& data, int& value) {
+    value = data.toInt();
+}
+
+void JSONReader::putData(const QJsonValue& data, uint& value) {
+    value = data.toInt();
+}
+
+void JSONReader::putData(const QJsonValue& data, float& value) {
+    value = data.toDouble();
+}
+
+void JSONReader::putData(const QJsonValue& data, QByteArray& value) {
+    value = QByteArray::fromPercentEncoding(data.toString().toLatin1());
+}
+
+void JSONReader::putData(const QJsonValue& data, QColor& value) {
+    value.setNamedColor(data.toString());
+}
+
+void JSONReader::putData(const QJsonValue& data, QScriptValue& value) {
+    QJsonObject object = data.toObject();
+    QString type = object.value("type").toString();
+    if (type == "UNDEFINED") {
+        value = QScriptValue(QScriptValue::UndefinedValue);
+        
+    } else if (type == "NULL") {
+        value = QScriptValue(QScriptValue::NullValue);
+    
+    } else if (type == "BOOL") {
+        value = QScriptValue(object.value("value").toBool());
+    
+    } else if (type == "NUMBER") {
+        value = QScriptValue(object.value("value").toDouble());
+    
+    } else if (type == "STRING") {
+        value = QScriptValue(object.value("value").toString());
+    
+    } else if (type == "VARIANT") {
+        QVariant variant;
+        putData(object.value("value"), variant);
+        value = ScriptCache::getInstance()->getEngine()->newVariant(variant);
+        
+    } else if (type == "QOBJECT") {
+        QObject* qObject;
+        putData(object.value("value"), qObject);
+        value = ScriptCache::getInstance()->getEngine()->newQObject(qObject, QScriptEngine::ScriptOwnership);
+    
+    } else if (type == "QMETAOBJECT") {
+        const QMetaObject* metaObject;
+        putData(object.value("value"), metaObject);
+        value = ScriptCache::getInstance()->getEngine()->newQMetaObject(metaObject);
+    
+    } else if (type == "DATE") {
+        QDateTime dateTime;
+        putData(object.value("value"), dateTime);
+        value = ScriptCache::getInstance()->getEngine()->newDate(dateTime);
+    
+    } else if (type == "REGEXP") {
+        QRegExp regExp;
+        putData(object.value("value"), regExp);
+        value = ScriptCache::getInstance()->getEngine()->newRegExp(regExp);
+    
+    } else if (type == "ARRAY") {
+        QJsonArray array = object.value("value").toArray();
+        value = ScriptCache::getInstance()->getEngine()->newArray(array.size());
+        for (int i = 0; i < array.size(); i++) {
+            QScriptValue element;
+            putData(array.at(i), element);
+            value.setProperty(i, element);
+        }
+    } else if (type == "OBJECT") {
+        QJsonObject jsonObject = object.value("value").toObject();
+        value = ScriptCache::getInstance()->getEngine()->newObject();
+        for (QJsonObject::const_iterator it = jsonObject.constBegin(); it != jsonObject.constEnd(); it++) {
+            QScriptValue element;
+            putData(it.value(), element);
+            value.setProperty(it.key(), element); 
+        }
+    } else {
+        value = QScriptValue();
+    }
+}
+
+void JSONReader::putData(const QJsonValue& data, QString& value) {
+    value = data.toString();
+}
+
+void JSONReader::putData(const QJsonValue& data, QUrl& value) {
+    value = data.toString();
+}
+
+void JSONReader::putData(const QJsonValue& data, QDateTime& value) {
+    value.setMSecsSinceEpoch((qint64)data.toDouble());
+}
+
+void JSONReader::putData(const QJsonValue& data, QRegExp& value) {
+    QJsonObject object = data.toObject();
+    value = QRegExp(object.value("pattern").toString(), (Qt::CaseSensitivity)object.value("caseSensitivity").toInt(),
+        (QRegExp::PatternSyntax)object.value("patternSyntax").toInt());
+    value.setMinimal(object.value("minimal").toBool());
+}
+
+void JSONReader::putData(const QJsonValue& data, glm::vec3& value) {
+    QJsonArray array = data.toArray();
+    value = glm::vec3(array.at(0).toDouble(), array.at(1).toDouble(), array.at(2).toDouble());
+}
+
+void JSONReader::putData(const QJsonValue& data, glm::quat& value) {
+    QJsonArray array = data.toArray();
+    value = glm::quat(array.at(0).toDouble(), array.at(1).toDouble(), array.at(2).toDouble(), array.at(3).toDouble());
+}
+
+void JSONReader::putData(const QJsonValue& data, const QMetaObject*& value) {
+    ObjectStreamerPointer streamer = _objectStreamers.value(data.toString());
+    value = streamer ? streamer->getMetaObject() : NULL;
+}
+
+void JSONReader::putData(const QJsonValue& data, QVariant& value) {
+    QJsonObject object = data.toObject();
+    QString type = object.value("type").toString();
+    const TypeStreamer* streamer = _typeStreamers.value(type).data();
+    if (!streamer) {
+        streamer = Bitstream::getTypeStreamers().value(QMetaType::type(type.toLatin1()));
+        if (!streamer) {
+            qWarning() << "Unknown type:" << type;
+            value = QVariant();
+            return;
+        }
+    }
+    streamer->putJSONData(*this, object.value("value"), value);
+}
+
+void JSONReader::putData(const QJsonValue& data, SharedObjectPointer& value) {
+    value = _sharedObjects.value(data.toInt()); 
+}
+
+void JSONReader::putData(const QJsonValue& data, QObject*& value) {
+    QJsonObject object = data.toObject();
+    ObjectStreamerPointer streamer = _objectStreamers.value(object.value("class").toString());
+    value = streamer ? streamer->putJSONData(*this, object) : NULL;
 }
 
 ObjectStreamer::ObjectStreamer(const QMetaObject* metaObject) :
@@ -1989,6 +2142,23 @@ QJsonObject MappedObjectStreamer::getJSONData(JSONWriter& writer, const QObject*
     return data;
 }
 
+QObject* MappedObjectStreamer::putJSONData(JSONReader& reader, const QJsonObject& jsonObject) const {
+    if (!_metaObject) {
+        return NULL;
+    }
+    QObject* object = _metaObject->newInstance();
+    QJsonArray properties = jsonObject.value("properties").toArray();
+    for (int i = 0; i < _properties.size(); i++) {
+        const StreamerPropertyPair& property = _properties.at(i);
+        if (property.second.isValid()) {
+            QVariant value;
+            property.first->putJSONData(reader, properties.at(i), value);
+            property.second.write(object, value);
+        }
+    }
+    return object;
+}
+
 void MappedObjectStreamer::write(Bitstream& out, const QObject* object) const {
     foreach (const StreamerPropertyPair& property, _properties) {
         property.first->write(out, property.second.read(object));
@@ -2093,6 +2263,19 @@ QJsonObject GenericObjectStreamer::getJSONData(JSONWriter& writer, const QObject
     return data;
 }
 
+QObject* GenericObjectStreamer::putJSONData(JSONReader& reader, const QJsonObject& jsonObject) const {
+    GenericSharedObject* object = new GenericSharedObject(_weakSelf);
+    QJsonArray properties = jsonObject.value("properties").toArray();
+    QVariantList values;
+    for (int i = 0; i < _properties.size(); i++) {    
+        QVariant value;
+        _properties.at(i).first->putJSONData(reader, properties.at(i), value);
+        values.append(value);
+    }
+    object->setValues(values);
+    return object;
+}
+
 void GenericObjectStreamer::write(Bitstream& out, const QObject* object) const {
     const QVariantList& values = static_cast<const GenericSharedObject*>(object)->getValues();
     for (int i = 0; i < _properties.size(); i++) {
@@ -2251,6 +2434,10 @@ QJsonValue TypeStreamer::getJSONVariantData(JSONWriter& writer, const QVariant&
     return data;   
 }
 
+void TypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+    value = QVariant();
+}
+
 bool TypeStreamer::equal(const QVariant& first, const QVariant& second) const {
     return first == second;
 }
@@ -2440,6 +2627,10 @@ QJsonValue EnumTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& val
     return value.toInt();
 }
 
+void EnumTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+    value = data.toInt();
+}
+
 TypeStreamer::Category EnumTypeStreamer::getCategory() const {
     return ENUM_CATEGORY;
 }
@@ -2532,6 +2723,11 @@ MappedEnumTypeStreamer::MappedEnumTypeStreamer(const TypeStreamer* baseStreamer,
     _mappings(mappings) {
 }
 
+void MappedEnumTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+    value = QVariant(_baseStreamer->getType(), 0);
+    _baseStreamer->setEnumValue(value, data.toInt(), _mappings);
+}
+
 QVariant MappedEnumTypeStreamer::read(Bitstream& in) const {
     QVariant object = QVariant(_baseStreamer->getType(), 0);
     int value = 0;
@@ -2608,6 +2804,10 @@ QJsonValue GenericEnumTypeStreamer::getJSONData(JSONWriter& writer, const QVaria
     return value.toInt();
 }
 
+void GenericEnumTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+    value = data.toInt();
+}
+
 void GenericEnumTypeStreamer::write(Bitstream& out, const QVariant& value) const {
     int intValue = value.toInt();
     out.write(&intValue, _bits);
@@ -2629,6 +2829,19 @@ MappedStreamableTypeStreamer::MappedStreamableTypeStreamer(const TypeStreamer* b
     _fields(fields) {
 }
 
+void MappedStreamableTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+    value = QVariant(_baseStreamer->getType(), 0);
+    QJsonArray array = data.toArray();
+    for (int i = 0; i < _fields.size(); i++) {
+        const StreamerIndexPair& pair = _fields.at(i);
+        if (pair.second != -1) {
+            QVariant element;
+            pair.first->putJSONData(reader, array.at(i), element);
+            _baseStreamer->setField(value, pair.second, element);    
+        }
+    }
+}
+
 QVariant MappedStreamableTypeStreamer::read(Bitstream& in) const {
     QVariant object = QVariant(_baseStreamer->getType(), 0);
     foreach (const StreamerIndexPair& pair, _fields) {
@@ -2709,6 +2922,17 @@ QJsonValue GenericStreamableTypeStreamer::getJSONData(JSONWriter& writer, const
     return array;
 }
 
+void GenericStreamableTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+    QJsonArray array = data.toArray();
+    QVariantList values;
+    for (int i = 0; i < _fields.size(); i++) {
+        QVariant element;
+        _fields.at(i).first->putJSONData(reader, array.at(i), element);
+        values.append(element);
+    }
+    value = values;
+}
+
 void GenericStreamableTypeStreamer::write(Bitstream& out, const QVariant& value) const {
     QVariantList values = value.toList();
     for (int i = 0; i < _fields.size(); i++) {
@@ -2733,6 +2957,15 @@ MappedListTypeStreamer::MappedListTypeStreamer(const TypeStreamer* baseStreamer,
     _valueStreamer(valueStreamer) {
 }
 
+void MappedListTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+    value = QVariant(_baseStreamer->getType(), 0);
+    foreach (const QJsonValue& element, data.toArray()) {
+        QVariant elementValue;
+        _valueStreamer->putJSONData(reader, element, elementValue);
+        _baseStreamer->insert(value, elementValue);
+    }
+}
+
 QVariant MappedListTypeStreamer::read(Bitstream& in) const {
     QVariant object = QVariant(_baseStreamer->getType(), 0);
     int size;
@@ -2791,6 +3024,17 @@ QJsonValue GenericListTypeStreamer::getJSONData(JSONWriter& writer, const QVaria
     return array;
 }
 
+void GenericListTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+    QJsonArray array = data.toArray();
+    QVariantList values;
+    foreach (const QJsonValue& element, array) {
+        QVariant elementValue;
+        _valueStreamer->putJSONData(reader, element, elementValue);
+        values.append(elementValue);
+    }
+    value = values;
+}
+
 void GenericListTypeStreamer::write(Bitstream& out, const QVariant& value) const {
     QVariantList values = value.toList();
     out << values.size();
@@ -2853,6 +3097,18 @@ MappedMapTypeStreamer::MappedMapTypeStreamer(const TypeStreamer* baseStreamer, c
     _valueStreamer(valueStreamer) {
 }
 
+void MappedMapTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+    value = QVariant(_baseStreamer->getType(), 0);
+    foreach (const QJsonValue& element, data.toArray()) {
+        QJsonArray pair = element.toArray();
+        QVariant elementKey;
+        _keyStreamer->putJSONData(reader, pair.at(0), elementKey);
+        QVariant elementValue;
+        _valueStreamer->putJSONData(reader, pair.at(1), elementValue);
+        _baseStreamer->insert(value, elementKey, elementValue);
+    }
+}
+
 QVariant MappedMapTypeStreamer::read(Bitstream& in) const {
     QVariant object = QVariant(_baseStreamer->getType(), 0);
     int size;
@@ -2926,6 +3182,20 @@ QJsonValue GenericMapTypeStreamer::getJSONData(JSONWriter& writer, const QVarian
     return array;
 }
 
+void GenericMapTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+    QJsonArray array = data.toArray();
+    QVariantPairList values;
+    foreach (const QJsonValue& element, array) {
+        QJsonArray pair = element.toArray();
+        QVariant elementKey;
+        _keyStreamer->putJSONData(reader, pair.at(0), elementKey);
+        QVariant elementValue;
+        _valueStreamer->putJSONData(reader, pair.at(1), elementValue);
+        values.append(QVariantPair(elementKey, elementValue));
+    }
+    value = QVariant::fromValue(values);
+}
+
 void GenericMapTypeStreamer::write(Bitstream& out, const QVariant& value) const {
     QVariantPairList values = value.value<QVariantPairList>();
     out << values.size();
diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h
index afacbf6dac..0cad33acea 100644
--- a/libraries/metavoxels/src/Bitstream.h
+++ b/libraries/metavoxels/src/Bitstream.h
@@ -449,6 +449,7 @@ private slots:
 
 private:
     
+    friend class JSONReader;
     friend class JSONWriter;
     
     ObjectStreamerPointer readGenericObjectStreamer(const QByteArray& name);
@@ -477,7 +478,7 @@ private:
     static QHash<QByteArray, const QMetaObject*>& getMetaObjects();
     static QMultiHash<const QMetaObject*, const QMetaObject*>& getMetaObjectSubClasses();
     static QHash<int, const TypeStreamer*>& getTypeStreamers();
-    
+         
     static const QHash<const QMetaObject*, const ObjectStreamer*>& getObjectStreamers();
     static QHash<const QMetaObject*, const ObjectStreamer*> createObjectStreamers();
     
@@ -793,8 +794,9 @@ public:
     QJsonValue getData(const QVariant& value);
     QJsonValue getData(const SharedObjectPointer& value);
     QJsonValue getData(const QObject* value);
+    QJsonValue getData(const GenericValue& value);
     
-    template<class T> QJsonValue getData(const T& value);
+    template<class T> QJsonValue getData(const T& value) { return QJsonValue(); }
     
     template<class T> QJsonValue getData(const QList<T>& list);
     template<class T> QJsonValue getData(const QVector<T>& list);
@@ -823,10 +825,6 @@ private:
     QJsonArray _typeStreamers;
 };
 
-template<class T> inline QJsonValue JSONWriter::getData(const T& value) {
-    return QJsonValue();
-}
-
 template<class T> inline QJsonValue JSONWriter::getData(const QList<T>& list) {
     QJsonArray array;
     foreach (const T& value, list) {
@@ -866,19 +864,88 @@ template<class K, class V> inline QJsonValue JSONWriter::getData(const QHash<K,
 class JSONReader {
 public:
     
-    JSONReader(const QJsonDocument& document);
+    JSONReader(const QJsonDocument& document, Bitstream::GenericsMode genericsMode = Bitstream::NO_GENERICS);
     
+    void putData(const QJsonValue& data, bool& value);
+    void putData(const QJsonValue& data, int& value);
+    void putData(const QJsonValue& data, uint& value);
+    void putData(const QJsonValue& data, float& value);
+    void putData(const QJsonValue& data, QByteArray& value);
+    void putData(const QJsonValue& data, QColor& value);
+    void putData(const QJsonValue& data, QScriptValue& value);
+    void putData(const QJsonValue& data, QString& value);
+    void putData(const QJsonValue& data, QUrl& value);
+    void putData(const QJsonValue& data, QDateTime& value);
+    void putData(const QJsonValue& data, QRegExp& value);
+    void putData(const QJsonValue& data, glm::vec3& value);
+    void putData(const QJsonValue& data, glm::quat& value);
+    void putData(const QJsonValue& data, const QMetaObject*& value);
+    void putData(const QJsonValue& data, QVariant& value);
+    void putData(const QJsonValue& data, SharedObjectPointer& value);
+    void putData(const QJsonValue& data, QObject*& value);
+    
+    template<class T> void putData(const QJsonValue& data, T& value) { value = T(); }
+    
+    template<class T> void putData(const QJsonValue& data, QList<T>& list);
+    template<class T> void putData(const QJsonValue& data, QVector<T>& list);
+    template<class T> void putData(const QJsonValue& data, QSet<T>& set);
+    template<class K, class V> void putData(const QJsonValue& data, QHash<K, V>& hash);
+    
+    template<class T> JSONReader& operator>>(T& value) { putData(*_contentsIterator++, value); return *this; }
+
     TypeStreamerPointer getTypeStreamer(const QString& name) const { return _typeStreamers.value(name); }
     ObjectStreamerPointer getObjectStreamer(const QString& name) const { return _objectStreamers.value(name); }
     SharedObjectPointer getSharedObject(int id) const { return _sharedObjects.value(id); }
 
 private:
     
+    QJsonArray _contents;
+    QJsonArray::const_iterator _contentsIterator;
+    
     QHash<QString, TypeStreamerPointer> _typeStreamers;
     QHash<QString, ObjectStreamerPointer> _objectStreamers;
     QHash<int, SharedObjectPointer> _sharedObjects;
 };
 
+template<class T> inline void JSONReader::putData(const QJsonValue& data, QList<T>& list) {
+    list.clear();
+    foreach (const QJsonValue& element, data.toArray()) {
+        T value;
+        putData(element, value);
+        list.append(value);
+    }
+}
+
+template<class T> inline void JSONReader::putData(const QJsonValue& data, QVector<T>& list) {
+    list.clear();
+    foreach (const QJsonValue& element, data.toArray()) {
+        T value;
+        putData(element, value);
+        list.append(value);
+    }
+}
+
+template<class T> inline void JSONReader::putData(const QJsonValue& data, QSet<T>& set) {
+    set.clear();
+    foreach (const QJsonValue& element, data.toArray()) {
+        T value;
+        putData(element, value);
+        set.insert(value);
+    }
+}
+
+template<class K, class V> inline void JSONReader::putData(const QJsonValue& data, QHash<K, V>& hash) {
+    hash.clear();
+    foreach (const QJsonValue& element, data.toArray()) {
+        QJsonArray pair = element.toArray();
+        K key;
+        putData(pair.at(0), key);
+        V value;
+        putData(pair.at(1), value);
+        hash.insert(key, value);
+    }
+}
+    
 typedef QPair<TypeStreamerPointer, QMetaProperty> StreamerPropertyPair;
 
 /// Contains the information required to stream an object.
@@ -895,6 +962,8 @@ public:
     virtual void writeMetadata(Bitstream& out, bool full) const = 0;
     virtual QJsonObject getJSONMetadata(JSONWriter& writer) const = 0;
     virtual QJsonObject getJSONData(JSONWriter& writer, const QObject* object) const = 0;
+    virtual QObject* putJSONData(JSONReader& reader, const QJsonObject& jsonObject) const = 0;
+    
     virtual void write(Bitstream& out, const QObject* object) const = 0;
     virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const = 0;
     virtual QObject* read(Bitstream& in, QObject* object = NULL) const = 0;
@@ -919,6 +988,7 @@ public:
     virtual void writeMetadata(Bitstream& out, bool full) const;
     virtual QJsonObject getJSONMetadata(JSONWriter& writer) const;
     virtual QJsonObject getJSONData(JSONWriter& writer, const QObject* object) const;
+    virtual QObject* putJSONData(JSONReader& reader, const QJsonObject& jsonObject) const;
     virtual void write(Bitstream& out, const QObject* object) const;
     virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const;
     virtual QObject* read(Bitstream& in, QObject* object = NULL) const;
@@ -941,6 +1011,7 @@ public:
     virtual void writeMetadata(Bitstream& out, bool full) const;
     virtual QJsonObject getJSONMetadata(JSONWriter& writer) const;
     virtual QJsonObject getJSONData(JSONWriter& writer, const QObject* object) const;
+    virtual QObject* putJSONData(JSONReader& reader, const QJsonObject& jsonObject) const;
     virtual void write(Bitstream& out, const QObject* object) const;
     virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const;
     virtual QObject* read(Bitstream& in, QObject* object = NULL) const;
@@ -1035,6 +1106,7 @@ public:
     virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
     virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const;
     virtual QJsonValue getJSONVariantData(JSONWriter& writer, const QVariant& value) const;
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const;
     
     virtual bool equal(const QVariant& first, const QVariant& second) const;
     
@@ -1093,6 +1165,8 @@ public:
     
     virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const {
         return writer.getData(value.value<T>()); }
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const {
+        T rawValue; reader.putData(data, rawValue); value = QVariant::fromValue(rawValue); }
     virtual bool equal(const QVariant& first, const QVariant& second) const { return first.value<T>() == second.value<T>(); }
     virtual void write(Bitstream& out, const QVariant& value) const { out << value.value<T>(); }
     virtual QVariant read(Bitstream& in) const { T value; in >> value; return QVariant::fromValue(value); }
@@ -1117,6 +1191,7 @@ public:
     virtual void writeMetadata(Bitstream& out, bool full) const;
     virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
     virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const;
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const;
     virtual Category getCategory() const;
     virtual int getBits() const;
     virtual QMetaEnum getMetaEnum() const;
@@ -1144,6 +1219,7 @@ public:
 
     MappedEnumTypeStreamer(const TypeStreamer* baseStreamer, int bits, const QHash<int, int>& mappings);
     
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const;
     virtual QVariant read(Bitstream& in) const;
     virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
     
@@ -1180,6 +1256,7 @@ public:
     virtual void writeMetadata(Bitstream& out, bool full) const;
     virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
     virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const;
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const;
     virtual void write(Bitstream& out, const QVariant& value) const;
     virtual QVariant read(Bitstream& in) const;
     virtual Category getCategory() const;
@@ -1212,6 +1289,7 @@ public:
 
     MappedStreamableTypeStreamer(const TypeStreamer* baseStreamer, const QVector<StreamerIndexPair>& fields);
     
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const;
     virtual QVariant read(Bitstream& in) const;
     virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
     
@@ -1230,6 +1308,7 @@ public:
     virtual void writeMetadata(Bitstream& out, bool full) const;
     virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
     virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const;
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const;
     virtual void write(Bitstream& out, const QVariant& value) const;
     virtual QVariant read(Bitstream& in) const;
     virtual Category getCategory() const;
@@ -1284,6 +1363,7 @@ public:
     
     MappedListTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& valueStreamer);
     
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const;
     virtual QVariant read(Bitstream& in) const;
     virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
     
@@ -1302,6 +1382,7 @@ public:
     virtual void writeMetadata(Bitstream& out, bool full) const;
     virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
     virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const;
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const;
     virtual void write(Bitstream& out, const QVariant& value) const;
     virtual QVariant read(Bitstream& in) const;
     virtual Category getCategory() const;
@@ -1366,6 +1447,7 @@ public:
     MappedMapTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& keyStreamer,
         const TypeStreamerPointer& valueStreamer);
     
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const;
     virtual QVariant read(Bitstream& in) const;
     virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
     
@@ -1386,6 +1468,7 @@ public:
     virtual void writeMetadata(Bitstream& out, bool full) const;
     virtual QJsonValue getJSONMetadata(JSONWriter& writer) const;
     virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const;
+    virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const;
     virtual void write(Bitstream& out, const QVariant& value) const;
     virtual QVariant read(Bitstream& in) const;
     virtual Category getCategory() const;
@@ -1421,6 +1504,7 @@ public:
     template<> void Bitstream::writeRawDelta(const X& value, const X& reference); \
     template<> void Bitstream::readRawDelta(X& value, const X& reference); \
     template<> QJsonValue JSONWriter::getData(const X& value); \
+    template<> void JSONReader::putData(const QJsonValue& data, X& value); \
     bool operator==(const X& first, const X& second); \
     bool operator!=(const X& first, const X& second); \
     static const int* _TypePtr##X = &X::Type;
@@ -1431,6 +1515,7 @@ public:
     template<> void Bitstream::writeRawDelta(const X& value, const X& reference); \
     template<> void Bitstream::readRawDelta(X& value, const X& reference); \
     template<> QJsonValue JSONWriter::getData(const X& value); \
+    template<> void JSONReader::putData(const QJsonValue& data, X& value); \
     bool operator==(const X& first, const X& second); \
     bool operator!=(const X& first, const X& second); \
     __attribute__((unused)) static const int* _TypePtr##X = &X::Type;
@@ -1442,6 +1527,7 @@ public:
     template<> void Bitstream::writeRawDelta(const X& value, const X& reference); \
     template<> void Bitstream::readRawDelta(X& value, const X& reference); \
     template<> QJsonValue JSONWriter::getData(const X& value); \
+    template<> void JSONReader::putData(const QJsonValue& data, X& value); \
     bool operator==(const X& first, const X& second); \
     bool operator!=(const X& first, const X& second); \
     static const int* _TypePtr##X = &X::Type; \
@@ -1453,7 +1539,8 @@ public:
     Bitstream& operator>>(Bitstream& in, S::N& obj); \
     template<> inline void Bitstream::writeRawDelta(const S::N& value, const S::N& reference) { *this << value; } \
     template<> inline void Bitstream::readRawDelta(S::N& value, const S::N& reference) { *this >> value; } \
-    template<> inline QJsonValue JSONWriter::getData(const S::N& value) { return (int)value; }
+    template<> inline QJsonValue JSONWriter::getData(const S::N& value) { return (int)value; } \
+    template<> inline void JSONReader::putData(const QJsonValue& data, S::N& value) { value = (S::N)data.toInt(); }
 
 #define IMPLEMENT_ENUM_METATYPE(S, N) \
     static int S##N##MetaTypeId = registerEnumMetaType<S::N>(&S::staticMetaObject, #N); \
diff --git a/tools/mtc/src/main.cpp b/tools/mtc/src/main.cpp
index eadccdb310..267e45a5a5 100644
--- a/tools/mtc/src/main.cpp
+++ b/tools/mtc/src/main.cpp
@@ -230,6 +230,19 @@ void generateOutput (QTextStream& out, const QList<Streamable>& streamables) {
         out << "    return array;\n";
         out << "}\n";
         
+        out << "template<> void JSONReader::putData(const QJsonValue& data, " << name << "& value) {\n";
+        out << "    QJsonArray array = data.toArray();\n";
+        out << "    QJsonArray::const_iterator it = array.constBegin();\n";
+        /* foreach (const QString& base, str.clazz.bases) {
+            out << "    foreach (const QJsonValue& element, getData(static_cast<const " << base << "&>(value)).toArray()) {\n";
+            out << "        array.append(element);\n";
+            out << "    }\n";
+        } */
+        foreach (const Field& field, str.fields) {
+            out << "    putData(*it++, value." << field.name << ");\n";
+        }
+        out << "}\n";
+        
         out << "bool operator==(const " << name << "& first, const " << name << "& second) {\n";
         if (str.clazz.bases.isEmpty() && str.fields.isEmpty()) {
             out << "    return true";