67 lines
1.9 KiB
Ruby
67 lines
1.9 KiB
Ruby
|
module Carto
|
||
|
# Rails 3 stores nil strings with JSON serialization as 'null', so we need to replace it with a valid value.
|
||
|
# See https://github.com/rails/rails/issues/13144
|
||
|
class CartoJsonSerializer
|
||
|
def self.dump(hash)
|
||
|
hash.try(&:to_json)
|
||
|
end
|
||
|
|
||
|
def self.load(value)
|
||
|
value.try(&:with_indifferent_access)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# CartoJsonSerializer is closer to Rails Json serializer, using with_indifferent_access
|
||
|
# for load. The problem with that is that although you can _access_ first
|
||
|
# level keys both with symbols and keys, other common operations, such as
|
||
|
# key comparison, fail, and it only applies to the first level.
|
||
|
class CartoJsonSymbolizerSerializer < CartoJsonSerializer
|
||
|
def self.load(value)
|
||
|
value && symbolize(value)
|
||
|
end
|
||
|
|
||
|
def self.symbolize(value)
|
||
|
if value.is_a?(Hash)
|
||
|
value.deep_symbolize_keys
|
||
|
elsif value.is_a?(Array)
|
||
|
value.map { |v| symbolize(v) }
|
||
|
else
|
||
|
value
|
||
|
end
|
||
|
end
|
||
|
private_class_method :symbolize
|
||
|
end
|
||
|
end
|
||
|
|
||
|
class CartoJsonSymbolizerValidator < ActiveModel::EachValidator
|
||
|
def validate_each(record, attribute, value)
|
||
|
if value && !(value.is_a?(Hash) || value.is_a?(Array))
|
||
|
record.errors[attribute] << 'wrongly formatted (not a Hash or invalid JSON)'
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
class JsonSchemaValidator < ActiveModel::EachValidator
|
||
|
def validate_each(record, attribute, value)
|
||
|
return unless value
|
||
|
|
||
|
value_for_json = prepare_for_json(value)
|
||
|
|
||
|
schema = Carto::Definition.instance.load_from_file("lib/formats/#{record.class.to_s.underscore}/#{attribute}.json")
|
||
|
errors = JSON::Validator::fully_validate(schema, value_for_json, strict: true)
|
||
|
record.errors[attribute] << errors.join(', ') if errors.any?
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def prepare_for_json(value)
|
||
|
if value.is_a? Hash
|
||
|
value.with_indifferent_access
|
||
|
elsif value.respond_to? :map
|
||
|
value.map { |v| prepare_for_json(v) }
|
||
|
else
|
||
|
value
|
||
|
end
|
||
|
end
|
||
|
end
|