Skip to content

Instantly share code, notes, and snippets.

@ascendbruce
Last active December 22, 2023 06:39
Show Gist options
  • Save ascendbruce/7070951 to your computer and use it in GitHub Desktop.
Save ascendbruce/7070951 to your computer and use it in GitHub Desktop.
Ruby test if a string is an valid json object

Background

I posted this gist a few years ago as a quick memo for myself. I never expect this little gist to rank up in top 3 search result and getting so many helpful feedbacks. Since it gets viewed quite often, I decided to revise this post so that it may be a little more helpful. Thank you again for the feedback!

The new answer

require "json"

class MyJSON
  def self.valid?(value)
    result = JSON.parse(value)

    result.is_a?(Hash) || result.is_a?(Array)
  rescue JSON::ParserError, TypeError
    false
  end
end
# true - valid JSON object
MyJSON.valid?(%({"a": "b", "c": 1, "d": true}))
MyJSON.valid?("{}")
MyJSON.valid?("[1, 2, 3]")

# false - may be a valid JSON string, but not a valid JSON object
MyJSON.valid?("")
MyJSON.valid?("123")

# false - not a valid JSON string
MyJSON.valid?(nil)
MyJSON.valid?(true)
MyJSON.valid?(123)

Ref: Is this simple string considered valid JSON?

Rationales

Why MyJSON class

So that it can be easily reused. But It's totally fine if you want to re-write it into a method, class or just copy part of the snippet.

why Checking is_a? Hash or Array

Because strings are valid JSON string and can be parsed successfully by JSON.parse.

But ensuring JSON objects is what I am looking for, thus extra checking is needed.

why rescue TypeError?

To handle edge cases like parsing JSON.parse(123)

Original answer (published in Oct 2013)

require "json"

def valid_json?(json)
  begin
    JSON.parse(json)
    return true
  rescue Exception => e
    return false
  end
end
@JsonSam
Copy link

JsonSam commented Nov 17, 2014

This method is not working. in method_missing': undefined methodvalid_json?' for #HTTParty::Response:0x00000002497918 (NoMethodError)

I have added require "json"

@Thermatix
Copy link

Where are you defining and using this? The problem is scope no doubt, you'd best be putting this into a class your calling using it calling that way . Also, don't ever rescue Exception, it will catch program exit signals as well and cause issues, for this you'll want to rescue JSON::ParserError.

@notjames
Copy link

I was looking at this and decided to refactor it a little to what I believe is cleaner. YMMV. Thanks for the base-idea, though!

def valid_json?(json)
    JSON.parse(json)
    true
rescue
    false
end

@benoittgt
Copy link

@notjames Don't rescue everything. Just rescue JSON::ParserError

@LucasArruda
Copy link

I would follow @benoittgt and only rescue from the specific error you are searching for.
And also, simplify by using !! operator.

def valid_json?(json)
  !!JSON.parse(json)
rescue JSON::ParserError => _e
  false
end

@foxmerald
Copy link

foxmerald commented Aug 12, 2019

this method will also return true for integers and floats -_-

json_valid?('42')
 => true 

json_valid?('57.13')
 => true 

Would go by

def valid_json?(string)
    hash = Oj.load(string)
    hash.is_a?(Hash) || hash.is_a?(Array)
rescue Oj::ParseError
    false
end

@ascendbruce
Copy link
Author

Hi everyone, thank you for all the feedbacks. I have updated my original answer. Hope it helps.

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