How to validate if a string is json in a Rails model
I suppose you could parse the field in question and see if it throws an error. Here's a simplified example (you might want to drop the double bang for something a bit clearer):
require 'json'
class String
def is_json?
begin
!!JSON.parse(self)
rescue
false
end
end
end
Then you could use this string extension in a custom validator.
validate :json_format
protected
def json_format
errors[:base] << "not in json format" unless json.is_json?
end
The best way is to add a method to the JSON module !
Put this in your config/application.rb :
module JSON
def self.is_json?(foo)
begin
return false unless foo.is_a?(String)
JSON.parse(foo).all?
rescue JSON::ParserError
false
end
end
end
Now you'll be enable to use it anywhere ('controller, model, view,...'), just like this :
puts 'it is json' if JSON.is_json?(something)
Currently (Rails 3/Rails 4) I would prefer a custom validator. Also see https://gist.github.com/joost/7ee5fbcc40e377369351.
# Put this code in lib/validators/json_validator.rb
# Usage in your model:
# validates :json_attribute, presence: true, json: true
#
# To have a detailed error use something like:
# validates :json_attribute, presence: true, json: {message: :some_i18n_key}
# In your yaml use:
# some_i18n_key: "detailed exception message: %{exception_message}"
class JsonValidator < ActiveModel::EachValidator
def initialize(options)
options.reverse_merge!(:message => :invalid)
super(options)
end
def validate_each(record, attribute, value)
value = value.strip if value.is_a?(String)
ActiveSupport::JSON.decode(value)
rescue MultiJson::LoadError, TypeError => exception
record.errors.add(attribute, options[:message], exception_message: exception.message)
end
end