Skip to content

Proposal to add JSON.safe_parse which rescues exceptions #785

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cizmarty opened this issue Apr 16, 2025 · 4 comments
Closed

Proposal to add JSON.safe_parse which rescues exceptions #785

cizmarty opened this issue Apr 16, 2025 · 4 comments

Comments

@cizmarty
Copy link

I propose adding helper method which rescues parsing error and returns nil by default.

# Returns `fallback` option (default `nil`) if source is not valid JSON.
def safe_parse(source, opts = {})
  Parser.parse(source, opts)
rescue JSONError
  opts[:fallback]
end

Motivation

In almost every project I deal with JSON-ish strings, which may or may not be a JSON. And every time I end up writing custom helper method just to rescue possible errors. I would love if this method was built-in.

Example usage

# Old way:
def fetch_http_error_message(body)
  # body is probably a JSON, but could be HTML or text or whatever.
  json = begin JSON.parse(body); rescue JSON::JSONError; nil; end
  json&.dig('message') || 'Unknown error'
end

# New way with safe_parse:
def fetch_http_error_code(body)
  # Safe parse ensures exception is never raised.
  JSON.safe_parse(body)&.dig('message') || 'Unknown error'

  # Or with fallback to empty hash:
  JSON.safe_parse(body, fallback: {})['message'] || 'Unknown error'
end

Notes

  • Named safe_parse as in it's safe, to call this method without errors. (Cannot use bang notation since both parse and parse! already exists and their behaviour is already defined.)
  • As far as I understand, safest option is to rescue JSONError which should cover any error which might raise fromJSON.parse operation. Any possible other errors should still be raised.

I would love feedback if this is something which could be added. Thanks!

@cizmarty cizmarty changed the title Proposal to introduce JSON.safe_parse which rescues exceptions Proposal to add JSON.safe_parse which rescues exceptions Apr 16, 2025
@byroot
Copy link
Member

byroot commented Apr 16, 2025

I'm not sure if this is really worth providing in JSON itself. I'll think about it.

The safe_parse name however isn't good, I assume you were inspired by Active Support's safe_constantize, but that's a pretty bad naming because it's really ambiguous what is safe about it.

Something more consistent with Ruby core methods would be try_parse, inspired by the various .try_convert methods in ruby core.

Another possible name is parse?, which I know would probably raise a few eyebrows but is fairly consistent with multiple ruby core methods.

As far as I understand, safest option is to rescue JSONError which should cover any error which might raise from JSON.parse operation.

Yes, which is why I don't see a very high value in this.

@cizmarty
Copy link
Author

Thanks for consideration, I really like name try_parse. With parse? I would probably assume it returns boolean, not the result.

Again, almost every time I use JSON.parse I just rescue and fallback to something else, because I don't want to break the flow - I'm curious if other people have same experience, maybe it's just me.

I know some libraries provide alternative methods which do not raise exceptions, but not sure about ruby core. The value is only in convenience, specifically when user doesn't need to handle exceptions / read docs / figure out which error should be rescued, etc.

@byroot
Copy link
Member

byroot commented Apr 17, 2025

maybe it's just me.

I would think so yes. That's why I'm not very enthusiastic about adding such method, I don't think it's a particularly common need, and only saves a rescue.

@byroot
Copy link
Member

byroot commented Apr 24, 2025

Alright. Thanks for the suggestion, but I don't think this feature is worth it.

@byroot byroot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants