lib/json_test_data/json_schema.rb
require_relative "./data_structures/string"
require_relative "./data_structures/number"
module JsonTestData
class JsonSchema
attr_accessor :schema, :handler
def initialize(schema, handler = nil)
@schema = JSON.parse(schema, symbolize_names: true)
@handler = handler
end
def generate_example
generate(schema).to_json
end
private
def generate_data(obj, key)
return handler.get_data(key, obj) if handler && handler.manages_key?(key)
case obj.fetch(:type)
when "number"
JsonTestData::Number.create(obj)
when "integer"
JsonTestData::Number.create(obj)
when "boolean"
true
when "string"
JsonTestData::String.create(obj)
end
end
def generate(obj, key = nil)
if is_object?(obj)
generate_object(obj)
elsif is_array?(obj)
generate_array(obj)
else
generate_data(obj, key)
end
end
def is_object?(property)
property.fetch(:type, nil) == "object"
end
def is_array?(property)
property.fetch(:type, nil) == "array"
end
def resolve_ref(object, ref)
ref = ref.split("/").map(&:to_sym)[1..-1]
ref.each {|key| object = object.fetch(key) }
object
end
def set_object(obj, schema)
schema.has_key?(:"$ref") ? resolve_ref(obj, schema.fetch(:"$ref")) : schema
end
def generate_object(object)
obj = {}
if object.has_key?(:oneOf)
schema_to_be_used = object.fetch(:oneOf).sample
object = set_object(object, schema_to_be_used)
end
if object.has_key?(:properties)
object.fetch(:properties).each do |k, v|
unless v.has_key?(:type)
obj[k] = nil
next
end
obj[k] = generate(v, k)
end
end
if object.has_key?(:minProperties) && obj.length < object.fetch(:minProperties, 0)
(object.fetch(:minProperties) - obj.length).times do
key = JsonTestData::String.create({type: "string"})
obj[key] = nil
end
end
obj.size == 0 ? {} : obj
end
def generate_array(object)
object.fetch(:minItems, nil) || object[:minItems] = 1
if object.fetch(:items, nil) && object.fetch(:items).has_key?(:type)
Array.new(object.fetch(:minItems)).map { generate(object.fetch(:items)) }
else
Array.new(object.fetch(:minItems))
end
end
end
end