Current section
Files
Jump to
Current section
Files
lib/json_data_faker.ex
defmodule JsonDataFaker do
@moduledoc """
Generate fake data based on json schema.
"""
alias ExJsonSchema.Schema
@doc """
generate fake data with given schema. It could be a raw json schema or ExJsonSchema.Schema.Root type.
## Examples
iex> schema = %{
...> "properties" => %{
...> "body" => %{"maxLength" => 140, "minLength" => 3, "type" => "string"},
...> "title" => %{"maxLength" => 64, "minLength" => 3, "type" => "string"}
...> },
...> "required" => ["title"],
...> "type" => "object"
...>}
iex> %{"title" => title, "body" => body} = JsonDataFaker.generate(schema)
"""
def generate(%Schema.Root{} = schema) do
generate_by_type(schema.schema)
end
def generate(schema) when is_map(schema) do
generate(Schema.resolve(schema))
rescue
_ ->
nil
end
def generate(_schema), do: nil
# private functions
defp generate_by_type(%{"type" => "boolean"}) do
Enum.random([true, false])
end
defp generate_by_type(%{"type" => "string"} = schema) do
generate_string(schema)
end
defp generate_by_type(%{"type" => "integer"} = schema) do
min = schema["minimum"] || 10
max = schema["maximum"] || 1000
Enum.random(min..max)
end
defp generate_by_type(%{"type" => "array"} = schema) do
inner_schema = schema["items"]
count = Enum.random(2..5)
Enum.map(1..count, fn _ ->
generate_by_type(inner_schema)
end)
end
defp generate_by_type(%{"type" => "object"} = schema) do
Enum.reduce(schema["properties"], %{}, fn {k, inner_schema}, acc ->
Map.put(acc, k, generate_by_type(inner_schema))
end)
end
defp generate_by_type(_schema), do: nil
defp generate_string(%{"format" => "date-time"}),
do: DateTime.utc_now() |> DateTime.to_iso8601()
defp generate_string(%{"format" => "uuid"}), do: Faker.UUID.v4()
defp generate_string(%{"format" => "email"}), do: Faker.Internet.email()
defp generate_string(%{"format" => "hostname"}), do: Faker.Internet.domain_name()
defp generate_string(%{"format" => "ipv4"}), do: Faker.Internet.ip_v4_address()
defp generate_string(%{"format" => "ipv6"}), do: Faker.Internet.ip_v6_address()
defp generate_string(%{"format" => "uri"}), do: Faker.Internet.url()
defp generate_string(%{"format" => "image_uri"}),
do: "https://source.unsplash.com/random/400x400"
defp generate_string(%{"enum" => choices}), do: Enum.random(choices)
defp generate_string(%{"pattern" => regex}),
do: Randex.stream(Regex.compile!(regex)) |> Enum.take(1) |> List.first()
defp generate_string(schema) do
min = schema["minLength"] || 0
max = schema["maxLength"] || 1024
s = Faker.Lorem.word()
case String.length(s) do
v when v > max -> String.slice(s, 0, max - 1)
v when v < min -> String.slice(Faker.Lorem.sentence(min), 0, min)
_ -> s
end
end
end