Skip to content

Instantly share code, notes, and snippets.

@ke4roh
Forked from binarydev/json_utilities.rb
Last active April 2, 2023 10:56
Show Gist options
  • Save ke4roh/348afe4a793d7d281071 to your computer and use it in GitHub Desktop.
Save ke4roh/348afe4a793d7d281071 to your computer and use it in GitHub Desktop.
declare module_function
source 'https://rubygems.org'
gem 'json'
group :test do
gem 'minitest'
gem 'test-unit'
end
module JsonUtilities
module_function
# compares two json objects (Array, Hash, or String to be parsed) for equality.
# Returns true if the objects are equivalent, false otherwise
def compare_json(json1, json2)
# return false if classes mismatch or don't match our allowed types
unless((json1.class == json2.class) && (json1.is_a?(String) || json1.is_a?(Hash) || json1.is_a?(Array)))
return false
end
# Parse objects to JSON if Strings
json1,json2 = [json1,json2].map! do |json|
json.is_a?(String) ? JSON.parse(json) : json
end
return compare_json0(json1, json2)
end
def compare_json0(json1, json2)
# initializing result var in the desired scope
result = false
# If an array, loop through each subarray/hash within the array and recursively call self with these objects for traversal
if(json1.is_a?(Array))
# Lengths must match
return false unless (json1.length==json2.length)
result = true # Zero length is also valid
json1.each_with_index do |obj, index|
json1_obj, json2_obj = obj, json2[index]
result = compare_json0(json1_obj, json2_obj)
# End loop once a false match has been found
break unless result
end
elsif(json1.is_a?(Hash))
# If a hash, check object1's keys and their values object2's keys and values
# first check that there are the same number of keys
return false unless (json1.keys.length==json2.keys.length)
# created_at and updated_at can create false mismatches due to occasional millisecond differences in tests
[json1,json2].each { |json| json.delete_if {|key,value| ["created_at", "updated_at"].include?(key)} }
json1.each do |key,value|
# both objects must have a matching key to pass
return false unless json2.has_key?(key)
json1_val, json2_val = value, json2[key]
result = compare_json0(json1_val, json2_val)
# End loop once a false match has been found
break unless result
end
end
return result ? true : (json1 == json2)
end
end
require_relative 'json_utilities'
require "minitest/autorun"
require 'json'
class TestJsonUtilities < MiniTest::Unit::TestCase
def test_same
initial=JSON.parse(<<eos)
{
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 25,
"height_cm": 167.6,
"address": {
"streetAddress": ["Big Street|6,5"],
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [],
"spouse": null
}
eos
test=JSON.parse(<<eos)
{"firstName": "John", "lastName": "Smith", "height_cm": 167.6, "age": 25, "address": {"streetAddress": ["Big Street|6,5"], "state": "NY", "postalCode": "10021-3100", "city": "New York"}, "isAlive": true, "spouse": null, "children": [], "phoneNumbers": [{"number": "212 555-1234", "type": "home"}, {"number": "646 555-4567", "type": "office"}]}
eos
puts JSON.pretty_generate(test)
assert(JsonUtilities.compare_json(initial,test),"Big comparison fails")
end
def test_empty_array_in_hash
assert(JsonUtilities.compare_json('{"foo": []}','{"foo": []}'))
end
def test_string_in_array
assert(JsonUtilities.compare_json('["foo"]','["foo"]'),"String in array fails")
end
def test_empty_array
assert(JsonUtilities.compare_json('[]','[]'))
end
def test_json2_hash_with_extra_key
a='{"foo":"bar"}'
b='{"foo":"bar", "bar":"baz"}'
assert(JsonUtilities.compare_json(a,b)==false,"fails with an extra key in jsonb")
assert(JsonUtilities.compare_json(b,a)==false,"fails with an extra key in jsona")
end
def test_null_hash_value_equality
a='{"foo": null}'
assert(JsonUtilities.compare_json(a,a))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment