c++qtqt4.8qjsonobject

JSON object Comparison in QT of same order and length


I have two objects which I wish to compare and display the differences of the values in the two objects. One is my reference object and another is my testing object. The order of the keys, the length of the objects are the same. The integer and float values in my object may slightly vary and I wish to display the difference to the user.

here is the code, and I wish to know if they will iterate through every value in my objects.

if(bool(refobject.length()==testobject.length())==true)
{
QJsonObject::iterator i,j;
for (i = refobject.begin(), j= testobject.begin(); 
              i!=refobject.end()&&j!=testobject.end(); ++i,++j)
{
if(i.key()==j.key())
   {     
   if(i.value().isString() && j.value().isString())
   { 
       if(i.value()==j.value())
       {
         //display i and j
       }
       else 
       {
        //display them in a different colour 
       }

     }
   else if(i.value().isArray()&& j.value().isArray())
   {
     //iterate and compare
   }
   else if(i.value().isObject() && j.value().isObject())
   {
      //check if there are strings or integers or array and work accordingly 
   }
   else if(i.value().isDouble() && j.value().isDouble())
   {
       if(i.value()==j.value())
       {
         //display i and j
       }
       else 
       {
          //display them in a different colour 
       }

   }

}
}
}

else{//display message that you cannot compare them}

I wish to know if this could help me iterate and compare the values in both objects.

Any other strategies to iterate through two json objects and compare the values would be greatly appreciated!

Thanks in advance!!!


Solution

  • I solved a similar problem: To search only the differences (deleted, created and changed values) and log these. My recursive algorithm works for all structures of JSON Strings. Basically it uses QJsonObject.keys() for Objects and QJsonArray.size() for Arrays for iteration and checks the difference for each value (which by itself is a JsonObject, JsonArray or JsonValue).

    JsonComparer.h

    #pragma once
    
    #include <qjsondocument.h>
    #include <qjsonarray.h>
    #include <qjsonobject.h>
    #include <qstringlist.h>
    
    class JsonComparer {
    public:
      QStringList compare(const QString json1, const QString json2);
    
    private:
      void compareObjects(QStringList keyStack, const QJsonObject obj1, const QJsonObject obj2);
      void compareArrays(QStringList keyStack, const QJsonArray arr1, const QJsonArray arr2);
      void compareValues(QStringList keyStack, const QJsonValue val1, const QJsonValue val2);
    
    private:
      QStringList m_differences;
    };
    

    JsonComparer.cpp

    #include "JsonComparer.h"
    #include <qvariant.h>
    #include <qdebug.h>
    
    QStringList JsonComparer::compare(const QString json1, const QString json2) {
      m_differences.clear();
    
      QJsonObject obj1 = QJsonDocument::fromJson(json1.toUtf8()).object();
      QJsonObject obj2 = QJsonDocument::fromJson(json2.toUtf8()).object();
      compareObjects(*(new QStringList()), obj1, obj2);
    
      return m_differences;
    }
    
    void JsonComparer::compareObjects(QStringList keyStack, const QJsonObject obj1, const QJsonObject obj2) {
      QStringList keysObj1 = obj1.keys();
      QStringList keysObj2 = obj2.keys();
    
      for (QString key : keysObj1) {
        if (!keysObj2.contains(key)) {
          m_differences << keyStack.join(", ") + ", " + key + ": deleted";
        }
      }
    
      for (QString key : keysObj2) {
        if (!keysObj1.contains(key)) {
          m_differences << keyStack.join(", ") + ", " + key + ": created";
        }
      }
    
      for (QString key : keysObj1) {
        if (keysObj2.contains(key)) {
          keyStack.append(key);
    
          if (obj1[key].isArray()) {        
            compareArrays(keyStack, obj1[key].toArray(), obj2[key].toArray());        
          }
          else if (obj1[key].isObject()) {
            compareObjects(keyStack, obj1[key].toObject(), obj2[key].toObject());
          }
          else {
            if (obj1[key] != obj2[key]) {
              compareValues(keyStack, obj1[key], obj2[key]);
            }
          }
    
          keyStack.removeLast();
        }
      }
    }
    
    void JsonComparer::compareArrays(QStringList keyStack, const QJsonArray arr1, const QJsonArray arr2) {
      quint32 minSize = qMin<int>(arr1.size(), arr2.size());
    
      for (quint32 i = 0; i < minSize; i++) {
        keyStack.append("[" + QString::number(i) + "]");
    
        if (arr1[i].isArray()) {      
          compareArrays(keyStack, arr1[i].toArray(), arr2[i].toArray());
        }
        else if (arr1[1].isObject()) {
          compareObjects(keyStack, arr1[i].toObject(), arr2[i].toObject());      
        }
    
        keyStack.removeLast();
      }  
    
      if (arr1.size() > arr2.size()) {
        for (quint32 i = minSize; i < arr1.size(); i++) {
          m_differences << keyStack.join(", ") + ", " + "[" + QString::number(i) + "]" + ": deleted";
        }
      }
    
      if (arr1.size() < arr2.size()) {    
        for (quint32 i = minSize; i < arr2.size(); i++) {
          m_differences << keyStack.join(", ") + ", " + "[" + QString::number(i) + "]" + ": created";
        }    
      }
    }
    
    void JsonComparer::compareValues(QStringList keyStack, const QJsonValue val1, const QJsonValue val2) {
      if (val1.isString()) {
        m_differences << keyStack.join(", ") + ": changed from " + val1.toString() + " to " + val2.toString();
      }
      else if (val1.isDouble()) {
        m_differences << keyStack.join(", ") + ": changed from " + QString::number(val1.toDouble()) + " to " + QString::number(val2.toDouble());
      }
    }
    

    As a sample output (i had to take some parts out):

    > Grills, [0]: deleted 
    > Grills, [1]: deleted 
    > LongName: changed from ... to ... 
    > ProductCode: changed from 321 to 474
    > RequestId: changed from 34E169A7-1E4E-7695-BA5C-5C277607BA5C to 5B6088D7-AF85-EECB-4D83-61FC179BA18F 
    > ShortName: changed from ... to ... 
    > attributes, OrderId: changed from 640 to 149 
    > attributes, OrderKey: changed from 0006:845097930 to 0001:205422059
    > attributes, PodType: changed from 8 to 0 
    > attributes, SaleDate: changed from 2019-01-20T13:31:04.1795784Z to 2019-01-20T13:45:46.5153031Z
    > attributes, SaleType: changed from 0 to 1