Skip to content

Instantly share code, notes, and snippets.

@chancancode
Created July 4, 2012 11:05
Show Gist options
  • Save chancancode/3046772 to your computer and use it in GitHub Desktop.
Save chancancode/3046772 to your computer and use it in GitHub Desktop.
JSON Matching
class MyTestCase < MiniTest::Unit::TestCase
# ...
WILDCARD_MATCHER = Object.new
def WILDCARD_MATCHER.==(other)
true
end
def WILDCARD_MATCHER.is_a?(klass)
false
end
def WILDCARD_MATCHER.inspect
'WILDCARD_MATCHER'
end
def assert_json_matches(matcher, json)
assert match_json(matcher, json), "Expected\n#{matcher.pretty_inspect}\nto match\n#{json.pretty_inspect}"
end
def match_json(matcher, json)
if matcher.is_a? Array
return false unless json.is_a? Array
return false unless match_array matcher, json
elsif matcher.is_a? Hash
return false unless json.is_a? Hash
return false unless match_hash matcher, json
elsif matcher.is_a? Regexp
return false unless matcher =~ json
else
return false unless matcher == json
end
true
end
def match_array(matcher, array)
return false unless matcher.length == array.length
matcher = matcher.clone
array = array.clone
begin
# This might fail
matcher.sort!
array.sort!
matched = []
matcher.zip(array).each_with_index do |(v1, v2), i|
matched << i if match_json v1, v2
end
matcher.delete_if.with_index { |_, i| matched.include? i }
array.delete_if.with_index { |_, i| matched.include? i }
rescue Exception
end
# O(N^2) matching for remaining items
matcher.each do |v1|
matched = false
array.each_with_index do |v2, i|
if match_json v1, v2
matched = true
array.delete_at i
break
end
end
return false unless matched
end
true
end
def match_hash(matcher, hash)
return false unless matcher.length == hash.length
return false unless matcher.keys.sort == hash.keys.sort
matcher.keys.each do |k|
return false unless match_json(matcher[k], hash[k])
end
true
end
end
@chancancode
Copy link
Author

t = MyTestCase.new(nil)

raw_json_str = '{ "a": 1, "b": true, "c": [1,2,3,4], "d": "abcdef", "e": "0123456789", "f": null, "g": {"aa": 1, "bb": {"aaa": 1} }, "h": "whatever" }'

t.assert_json_matches({
  'a' => 1,
  'b' => true,
  'c' => [4,1,3,2],
  'd' => 'abcdef',
  'e' => /[0-9]{10}/,
  'f' => nil,
  'g' => {
    'aa' => 1,
    'bb' => {
      'aaa' => 1
    }
  },
  'h' => MyTestCase::WILDCARD_MATCHER
}, JSON.parse(raw_json_str) )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment