# JSON matcher

**URL:** <https://www.ruby-forum.com/t/json-matcher/164891>\
**Category:** RSpec\
**Created:** [April 7, 2009, 4:14am UTC](https://www.ruby-forum.com/t/json-matcher/164891 "2009-04-07T04:14:50Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![wickie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/ba9def/32.png) [@wickie](https://www.ruby-forum.com/u/wickie)\
**Post date:** [April 7, 2009, 4:14am UTC](https://www.ruby-forum.com/t/json-matcher/164891/1 "2009-04-07T04:14:50Z")

</div>

Curiously, there doesn’t seem to be a matcher around that matches a JSON  
string against an expected ruby object. Below is what I’ve come up  
with, including some Rails idiosyncrasies. Any suggestions for  
improvements?

Michael

module Spec  
module JSONMatchers  
class BeJsonEql  
def initialize(expected)  
@raw\_expected = expected  
@expected = decode(expected, ‘expected’)  
end

```
  def matches?(target)
    @raw_target = target
    @target = decode(target, 'target')
    @target == @expected
  end

  def failure_message
    "expected\n#{@raw_target}\n" +
    "to be JSON code equivalent to\n#{@raw_expected}\n" +
    "Difference:\n#{@expected.diff(@target).inspect}"
  end

  def negative_failure_message
    "expected\n#{@raw_target}\n" +
    "to be JSON code different from\n#{@raw_expected}"
  end

  private

  def decode(s, which)
    ActiveSupport::JSON.decode(s)
  rescue ActiveSupport::JSON::ParseError
    raise ArgumentError, "Invalid #{which} JSON string:

```

#{s.inspect}"  
end  
end

```
def be_json_eql(expected)
  BeJsonEql.new(expected)
end

```

end  
end

–  
Michael S.  
[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
[http://www.schuerig.de/michael/](http://www.schuerig.de/michael/)

---

<div class="post-metadata">

**Author:** ![wickie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/ba9def/32.png) [@wickie](https://www.ruby-forum.com/u/wickie)\
**Post date:** [April 7, 2009, 4:25am UTC](https://www.ruby-forum.com/t/json-matcher/164891/2 "2009-04-07T04:25:22Z")

</div>

Michael S. wrote:

> ```
> def failure_message
> "expected\n#{@raw_target}\n" +
> "to be JSON code equivalent to\n#{@raw_expected}\n" +
> "Difference:\n#{@expected.diff(@target).inspect}"
> end
> 
> ```

Nice - this fixes the common problem with assertions on large bulky  
variables -  
they often leave you squinting, trying to see the line that’s different.

But where did .diff() come from? should I know it’s part of  
ActiveSupport::JSON  
or something?

---

<div class="post-metadata">

**Author:** ![wickie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/ba9def/32.png) [@wickie](https://www.ruby-forum.com/u/wickie)\
**Post date:** [April 7, 2009, 9:48am UTC](https://www.ruby-forum.com/t/json-matcher/164891/3 "2009-04-07T09:48:33Z")

</div>

On Tuesday 07 April 2009, Phlip wrote:

> But where did .diff() come from? should I know it’s part of  
> ActiveSupport::JSON or something?

Hash#diff is part of ActiveSupport and when you look at its code you’ll  
probably have to squint.

Michael

–  
Michael S.  
[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
[http://www.schuerig.de/michael/](http://www.schuerig.de/michael/)

---

<div class="post-metadata">

**Author:** ![wickie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/ba9def/32.png) [@wickie](https://www.ruby-forum.com/u/wickie)\
**Post date:** [May 19, 2011, 10:03pm UTC](https://www.ruby-forum.com/t/json-matcher/164891/4 "2011-05-19T22:03:17Z")

</div>

JSON matcher updated (works with Rspec 1.3.1). Put this in  
spec/support/matchers/json\_matcher.rb:

Spec::Matchers.define :be\_json\_eql do | expected |  
match do | actual |  
@expected = decode(expected, ‘expected’)  
@actual = decode(actual, ‘actual’)  
@actual == @expected  
end

failure\_message\_for\_should do | actual |  
“expected\n#{actual}\n” +  
“to be JSON code equivalent to\n#{expected}\n” +  
“Difference:\n#{@expected.diff(@actual).inspect}”  
end

failure\_message\_for\_should\_not do | actual |  
“expected\n#{actual}\n” +  
“to be JSON code different from\n#{expected}”  
end

def decode(s, which)  
ActiveSupport::JSON.decode(s)  
rescue ActiveSupport::JSON::ParseError  
raise ArgumentError, “Invalid #{which} JSON string:  
#{s.inspect}”  
end  
end
