Tencent / rapidjson

A fast JSON parser/generator for C++ with both SAX/DOM style API
http://rapidjson.org/
Other
14.23k stars 3.54k forks source link

Compare Unkown jsonstring with Nested arrays #1224

Open Bishalsahoo opened 6 years ago

Bishalsahoo commented 6 years ago

Hello , I am a bit stuck in comparing two json strings

  #include <iostream>
   #include "include/rapidjson/document.h"
   #include "include/rapidjson/writer.h"
   #include "include/rapidjson/prettywriter.h"
   //#include "include/rapidjson/stringbuffer.h"
    using namespace std;
    using namespace rapidjson;

   class test {
    public:
     static bool isEqual(const string &item1, const string &item2, const string &temp) {
      Document d1;
      d1.Parse(item1.c_str());
      Document d2;
      d2.Parse(item2.c_str());
      Document d3;
       d3.Parse(temp.c_str());
       bool a = true;
       bool b = isJsonEqual(d1, d2, d3, a);

      }

     static bool isJsonEqual(Value &v, Value &v1, Value &v2, bool &a) {
      /*
      StringBuffer buffer;

    PrettyWriter<StringBuffer> writer(buffer);

    v.Accept(writer);
    //cout<<buffer.GetString()<<endl;
    StringBuffer b1;
    PrettyWriter<StringBuffer> writer1(b1);
    v1.Accept(writer1);
    //cout<<b1.GetString()<<endl;
    StringBuffer b2;
    PrettyWriter<StringBuffer> writer2(b2);
    v2.Accept(writer2);
     //cout<<b2.GetString()<<endl;
    */

    for (auto itr = v2.MemberBegin(); itr != v2.MemberEnd(); itr++) {
        if (itr->value.IsArray()) {
    /*            StringBuffer b3;
            PrettyWriter<StringBuffer> writer3(b3);
            v2[itr->name].Accept(writer3);
            cout << b3.GetString() << endl;*/
            auto c = itr->name.GetString();

            cout << c << endl;

     isJsonEqual(v[itr->name],v1[itr->name],v2[itr->name],a);    

/ CAN ANYONE PLEASE HELP ME WITH THIS RECURSION (I WANT TO SEND THE ARRAY AS PARAMETER(LIKE I PREVIOUSLY RECEIVED THE JSON VALUE ASTER PARSING TO THE RESPECTIVE VALUE FIELD OF THE isJsonEqual(VALUE &,VALUE&,VALUE&,A) /

     } else if (v.HasMember(itr->name) && v1.HasMember(itr->name)) {
            // cout<<itr->name.GetString()<<endl;
            if ((v[itr->name]) != v1[itr->name]) {

                a = false;
                break;
            }
        }
    }

}

    };

           int main() {
           const char *item7 = "{  \"array\": [    1,    2,    3  ],  \"boolean\": true,  \"null\": null,  \"number\": 
           123,  \"object\": {    \"a\": \"b\",    \"c\": \"d\",    \"e\": \"f\"  },  \"string\": \"Hello World\",   
           \"object_array\": [     {\"key\": \"value1\" },     {\"key\": \"value2\" },     {\"key\": \"value3\" }    ],    
          \"deep_nested_array\": [        {\"object_array1\": [     {\"key\": \"value1\" },     {\"key\": \"value2\" },     
          {\"key\": \"value3\" }    ]},    {\"object_array2\": [     {\"key\": \"value4\" },     {\"key\": \"value5\" },     
          {\"key\": \"value6\" }    ]}      ]}";
          const char *item8 = "{ \"array\": [    1,    2,    3  ],   \"justsomedata\": true,  \"boolean\": true,  
          \"null\": null,  \"object\": {    \"a\": \"b\",    \"c\": \"d\",    \"e\": \"f\"  },  \"number\": 123,  
         \"object_array\": [     {\"whatever\": \"test\", \"key\": \"value1\" },     {\"key\": \"value2\" },     {\"key\": 
         \"value3\" }    ],    \"deep_nested_array\": [        {\"object_array1\": [     {\"key\": \"value1\" },     
         {\"key\": \"value2\" },     {\"key\": \"value3\" }    ]},    {\"object_array2\": [     {\"key\": \"value4\" },     
        {\"key\": \"value5\" },     {\"key\": \"value6\", \"ignoreme\": 12346 }    ]}      ],  \"string\": \"Hello 
        World\"}";
         const char *temp3 = "{  \"array\": [    null  ],  \"boolean\": null,  \"null\": null,  \"object\": {    \"a\": 
         null,    \"c\": null,    \"e\": null  },  \"number\": null,  \"object_array\": [     {\"key\": null }    ],    
        \"deep_nested_array\": [        {\"object_array1\": [     {\"key\": null },     {\"key\": null },     {\"key\": 
           null }    ]}      ],  \"string\": null}";

      bool a = test::isEqual(item7, item8, temp3);
           if (a) {
          cout << "True";
          //std::cout << "Verify again" << std::endl;
          } else {
           cout << "check again";
           }
         }

Here I am able to compare the simple Json with single array but when there are n number of nested array it doesnt works the way it should be . I need it to loop into array element and check them individually as there might be sub array . I tried to do that with assert(d1[itr->name.IsArray()]) but it will be a same problem if it has more subarrays in those sub array cant write loops to find if the key is an arrary till n number of times and if there is any other functionality in rapidjson I am unknown as I am absolutely new to rapidjson. Can anyone please help me complete the code to make it effective ? In the above case the object_array and deep_nested_array are the one that mismatch even though they are same according to the stencil(the reference) . The output should be true but it is false instead. Please help me with this.

Bishalsahoo commented 6 years ago

@miloyip can you help me please ? Its kinda urgent . Hope for your response soon

miloyip commented 6 years ago

I haven't digged into your code. Why not just using d1 == d2 ?

Bishalsahoo commented 6 years ago

i want to compare the keys that only exists in the reference template(stencil)

Bishalsahoo commented 6 years ago

https://drive.google.com/open?id=1HY-jfMId7qELNZdm2Iu1tXP-QZr2e-9y please have a look into the raw json. My code is not diving deep enough to get and compare array inside deep_nested_array

miloyip commented 6 years ago

I think that you want to validate a JSON to ensure it conforms to your "template". RapidJSON supports JSON Schema which can do it simply by defining a JSON schema. You may check about what is JSON schema (e.g. here), and then figure how to use it in RapidJSON in here.

Bishalsahoo commented 6 years ago

Yes I want to validate values of two json based on the template and I will be going through that but your help to complete the code will be very helpful as it is kinda urgent please @miloyip . I am unable to find a way to iterate through the inner nested array elements

miloyip commented 6 years ago

I cannot help finishing your own work. Please understand.

Bishalsahoo commented 6 years ago

No I know that but can you show me the way to iterate into nested array get the elements and check if the value in the array is another array and loop in its value to check if they are equal , just need help with this logic as i am able to enter the array (for instance deep_nested_array in this case )but unable to iterate thought the sub array and check the value. whatever i try is showing error . Just help me with the logic I will be able to complete it

Bishalsahoo commented 6 years ago

I tried to use the schema too but the problem is the parser is unable to detect the sub nested array and just returns the key on the outer loop , because of that it compares the value of deep_nested_array rather than going deep into it to get the object_array and the key elements inside it. I need a way to get the keys inside the deep_nested_array and then inside the object_array. As I mentioned i tried to loop inside the deep_nested_array and get the index numbers but unable to access the sub element object in it and loop inside them(ie i can loop inside the 1st array but unable to get value or key to compare and loop further with in them). Please help me just with the logic, how to do it.

Bishalsahoo commented 6 years ago

Can anyone help me to complete the correct way of recursion by passing the value parameter back to continue the loop for the deeper array (Please refer the post above). @miloyip