JSON Сравнение объектов в QT того же порядка и длины - PullRequest
2 голосов
/ 03 апреля 2020

У меня есть два объекта, которые я буду sh сравнивать и отображать различия значений в двух объектах. Один - это мой эталонный объект, а другой - мой объект тестирования. Порядок клавиш, длина объектов одинаковы. Целочисленные значения и значения с плавающей точкой в ​​моем объекте могут незначительно отличаться, и я буду sh отображать разницу для пользователя.

вот код, и я буду sh, чтобы знать, будут ли они повторяться через каждый значение в моих объектах.

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}

Я бы хотел sh узнать, может ли это помочь мне перебрать и сравнить значения в обоих объектах.

Любые другие стратегии для перебора двух json объекты и сравнить значения будет принята с благодарностью!

Спасибо заранее !!!

1 Ответ

1 голос
/ 04 апреля 2020

Я решил похожую проблему: искать только различия (удаленные, созданные и измененные значения) и регистрировать их. Мой рекурсивный алгоритм работает для всех структур JSON строк. В основном он использует QJsonObject.keys () для объектов и QJsonArray.size () для массивов для итерации и проверяет разницу для каждого значения (которое само по себе является JsonObject, JsonArray или 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());
  }
}

В качестве примера вывода (мне пришлось вынуть некоторые детали):

> 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
...