oj: "NoMethodError: undefined method `json_create' for Regexp:Class" trying to deserialize json regex (conflict with Pact gem).

We’re using the Pact gem as more and more teams are for testing micro-services: https://github.com/realestate-com-au/pact

I get this error if Pact is loaded after oj but not if Pact is loaded before oj:

*** Loading Pact before oj ***

|ruby-2.3.1@test_oj| Gals-MacBook-Pro-2 in ~/workspace/test_oj
○ → irb
2.3.1 :001 > require 'json'
 => true
2.3.1 :002 > require 'pact'
 => true
2.3.1 :003 > require 'oj'
 => true
2.3.1 :004 > require 'oj_mimic_json'
 => true
2.3.1 :005 > /1/.to_json
 => "{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"1\"}"
2.3.1 :006 > JSON.load(/1/.to_json)
 => /1/
2.3.1 :007 > exit

Loading oj before pact*

|ruby-2.3.1@test_oj| Gals-MacBook-Pro-2 in ~/workspace/test_oj
○ → irb
2.3.1 :001 > require 'json'
 => true
2.3.1 :002 > require 'oj'
 => true
2.3.1 :004 > require 'oj_mimic_json'
 => true
2.3.1 :005 > require 'pact'
 => true
2.3.1 :006 > /1/.to_json
 => "{}"
2.3.1 :007 > JSON.load(/1/.to_json)
 => {}
2.3.1 :008 > JSON.load("{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"1\"}")
NoMethodError: undefined method `json_create' for Regexp:Class
Did you mean?  json_creatable?
    from (irb):8:in `load'
    from (irb):8
    from /Users/gal/.rvm/rubies/ruby-2.3.1/bin/irb:11:in `<main>'
2.3.1 :009 >

^^^ This is the error I’m getting in my Pact Test suites currently, if I use a regex matcher.

Pact does some overriding of Regexp json serializer, and it does seem to fix a real problem:

https://github.com/bethesque/pact-support/blob/master/lib/pact/shared/active_support_support.rb#L23

Active Support without Pact

○ → irb
2.3.1 :001 > require 'rails/all'
 => true
2.3.1 :002 > /1/.to_json
 => "\"(?-mix:1)\""
2.3.1 :003 > JSON.load(/1/.to_json)
 => "(?-mix:1)"

(it deserializes the regex into a weird string). Note that plain ruby, with just require 'json' behaves the same way as require 'rails/all'. So maybe thats the correct or at least “standard” behavior but it doesn’t seem like a good one:

ruby with json

|ruby-2.3.1@test_oj| Gals-MacBook-Pro-2 in ~/workspace/test_oj
○ → irb
2.3.1 :001 > require 'json'
 => true
2.3.1 :002 > require 'multi_json'
 => true
2.3.1 :003 > /1/.to_json
 => "\"(?-mix:1)\""
2.3.1 :004 > JSON.load(/1/.to_json)
 => "(?-mix:1)"

Active Support With Pact

○ → irb
2.3.1 :001 > irb
2.3.1 :001 > ^C
2.3.1 :001 > require 'rails/all'
 => true
2.3.1 :002 > require 'pact'
 => true
2.3.1 :003 > /1/.to_json
 => "{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"1\"}"
2.3.1 :004 > JSON.load(/1/.to_json)
 => /1/

Works right! I guess Pact’s patch is necessary.

At this point I’m not even sure what is the expected correct behavior.

This is the actual line in Pact that throws the error:

https://github.com/bethesque/pact-mock_service/blob/aadbb8dd5fb9f91ed0d5b1c7ed07006d1282350e/lib/pact/mock_service/request_handlers/interaction_post.rb#L24

(the JSON.load).

Finally, I realize you might tell me that this is a problem with Pact and that they shouldn’t patch the way they’re patching, and if thats the case, thats fine. But I wanted to check in here to at least find out what is the expected behavior, and to see if you have any suggestions. (or at the very least some thoughts on the correct way to handle in the ideal case both in oj and in pact)

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 28 (16 by maintainers)

Most upvoted comments

Great, I’ll release later tonight.