-3

I have two JSON arrays as below

# Array1

[
  {
    "objectId": "34fc6a0c-be91-4a6d-b5dd-20ae347085c7",    
    "model": "robotics.energy",
    "timestamp": "2020-08-07T12:36:40.697Z",
    "value": 2.0
  },
  {
    "objectId": "34fc6a0c-be91-4a6d-b5dd-20ae347085c7",    
    "model": "robotics.energy",
    "timestamp": "2020-08-07T12:36:40.697Z",
    "value": 4459.477340033425
  }
]

# Array2

[
 {
    "model": "robotics.energy",
    "objectId": "34fc6a0c-be91-4a6d-b5dd-20ae347085c7",       
    "timestamp": "2020-08-07T12:36:40.697Z",
    "value": 4459.477340033425
  },
  {
    "timestamp": "2020-08-07T12:36:40.697Z",
    "objectId": "34fc6a0c-be91-4a6d-b5dd-20ae347085c7",    
    "model": "robotics.energy",   
    "value": 2.0
  }
]

I want to assert those two arrays are equal or not.

I tried s below. But it fails since order of the elements are different

var jarray1 = JArray.Parse(Array1);
var jarray2 = JArray.Parse(Array2);
JArray.DeepEquals(jarray1, jarray2); 

Tried as below anyway it throws error as Icomparable interface is not implemented.

Enumerable.SequenceEqual(jarray1 .OrderBy(t => t), jarray2.OrderBy(t => t)).Should().BeTrue();   

                 

Is there any easy solution exist?

I thought of converting it to string then sort it and verify it. But I felt that's not good way.

KBNanda
  • 595
  • 1
  • 8
  • 25
  • Why not deserialize to a List which implements a compare method? – Ňɏssa Pøngjǣrdenlarp Aug 07 '20 at 13:52
  • @ŇɏssaPøngjǣrdenlarp I need to create a class to deserialize it. Isn't it? I don't want to do that. – KBNanda Aug 07 '20 at 13:57
  • 2
    Is there any technical reason we have missed for the "_I don't want to do that_". Creating a class is a simple copy past either in online tool like [Json 2 CSharp](https://json2csharp.com/) or [QuickType](https://app.quicktype.io/) or a simple special past in any Visual Studio since 2011. I believe that one can copy past those 2 json create class and order by a property in around 3 minutes using one hand. – Drag and Drop Aug 07 '20 at 14:03
  • If the order of the data is different, then sort the data before comparing. To sort, you need to sort by the properties in the objects, not the objects themselves (this is easier and type-safe if you create a class). – crashmstr Aug 07 '20 at 14:03
  • If you fail on any on those step please tell us so we can point to the correct duplicate. Deserialise a Json to a List, "How to Sort a List by a property in the object", or "Compare two List objects for equality, ignoring order" – Drag and Drop Aug 07 '20 at 14:08
  • If you have special constaint like "Given 2 arbitrary Json Array" then I will recommend building an [MRE] with edge case like "array of one element compare to this one element solo". State the nesting level of those etc. You could for example use `foreach (JToken child in JObject.Parse(jsonString).Children())`, and enumerate the object and test if the current child is a property or an array. With some reccurtion – Drag and Drop Aug 07 '20 at 14:13
  • @DragandDrop Thanks. I can do creating class and deserializing it. No rule like I can't do that :-). But I was thinking of any other alternative exists. Because I do more comparisons like this with different set of keys and I end up creating so many classes. – KBNanda Aug 07 '20 at 14:18
  • You have to work on the specification a little more. How could you order if you don't know the property name? But if a property is an array you will have to order the property value too. But you didn't knew about the property name, how could you figure a key to filter it. – Drag and Drop Aug 07 '20 at 14:23
  • Each of those problem have solution, we can not solve a problem with a nested unlimited amount of problem. You have to specify the rules. – Drag and Drop Aug 07 '20 at 14:26
  • @DragandDrop I thought of ordering by Key Name like "model", "objectId", "timestamp" and "value" inside array item and then order the entire array by "value". But the question comes like when we have same "value" array what will happen. Hence I believe deserializing and verifying is the only option left. But I wonder why can't we have a readymade library assertion method for this. – KBNanda Aug 07 '20 at 14:30
  • Because no library will assume that there is a property name "model" or "objectId", or the type of a property. For example : Let go for time stamp.. They are all the same 01/01/1900.. The array or sub array is not order comparaison failed. And we did not address the dictionary serialisation style. Or time that have the same value but not the same representation. – Drag and Drop Aug 07 '20 at 14:34
  • 1
    But your problem is not comparing but ordering once you have two item ordered. You can just serialize and compare the result you don't have to iterate with reflexion. – Drag and Drop Aug 07 '20 at 14:36
  • https://stackoverflow.com/questions/4332635/c-sharp-compare-two-objects-of-unknown-types-including-reference-and-value-type, and linked question may help. I try to help with my humble knowledge perhaps I missed something. But imo for testing purpuse I will go for DTO/Class, that a few click. – Drag and Drop Aug 07 '20 at 14:44
  • @DragandDrop Thanks for your perseverance on answering my queries. I settled by deserializing into class. If you come across any other alternative comparison please do add it as answer. – KBNanda Aug 07 '20 at 15:51

1 Answers1

0

Created classes as below for de-serializing it.

public class Telemetry
    {
        [JsonProperty("model")]
        public string Model { get; set; }

        [JsonProperty("objectId")]
        public string ObjectId { get; set; }

        [JsonProperty("timestamp")]
        public string Timestamp { get; set; }

        [JsonProperty("value")]
        public object Value { get; set; }     
    }

public class TelemetryRoot
    {
        public List<Telemetry> Telemetries { get; set; }
    }

Then did as below to compare the deserialized objects.

var array1Obj = JsonConvert.DeserializeObject<List<TelemetryRoot>>(Array1);
var array2Obj = JsonConvert.DeserializeObject<List<TelemetryRoot>>(Array2);
array1Obj.Should().BeEquivalentTo(array2Obj);     //using fluent assertions
KBNanda
  • 595
  • 1
  • 8
  • 25