88 lines
3.2 KiB
C#
88 lines
3.2 KiB
C#
using EonaCat.DoxaApi.Models;
|
|
|
|
namespace EonaCat.DoxaApi.Generation
|
|
{
|
|
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
|
// See the LICENSE file or go to https://EonaCat.com/license for full license details.
|
|
|
|
/// <summary>
|
|
/// Produces schema-shaped, deterministic-but-plausible fake JSON values for a given
|
|
/// <see cref="SchemaModel"/>. Used by the built-in mock server so that frontend teams
|
|
/// can develop against an API before its real implementation exists.
|
|
/// </summary>
|
|
public static class MockResponseGenerator
|
|
{
|
|
public static object? Generate(SchemaModel? schema, ApiDocument doc, int depth = 0, HashSet<string>? seen = null)
|
|
{
|
|
seen ??= new HashSet<string>();
|
|
if (schema is null || depth > 8)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (schema.RefName is not null)
|
|
{
|
|
if (!seen.Add(schema.RefName))
|
|
{
|
|
return new Dictionary<string, object?>();
|
|
}
|
|
|
|
if (doc.Schemas.TryGetValue(schema.RefName, out var resolved))
|
|
{
|
|
return Generate(resolved, doc, depth + 1, seen);
|
|
}
|
|
|
|
return new Dictionary<string, object?>();
|
|
}
|
|
|
|
switch (schema.Type)
|
|
{
|
|
case "string":
|
|
return MockString(schema.Format);
|
|
case "integer":
|
|
return RandomInt(depth);
|
|
case "number":
|
|
return Math.Round(RandomInt(depth) + 0.5, 2);
|
|
case "boolean":
|
|
return depth % 2 == 0;
|
|
case "enum":
|
|
return schema.EnumValues?.Count > 0 ? schema.EnumValues[0] : "value";
|
|
case "array":
|
|
return new List<object?>
|
|
{
|
|
Generate(schema.Items, doc, depth + 1, seen),
|
|
Generate(schema.Items, doc, depth + 1, seen)
|
|
};
|
|
case "object":
|
|
{
|
|
if (schema.Properties is null)
|
|
{
|
|
return new Dictionary<string, object?>();
|
|
}
|
|
|
|
var obj = new Dictionary<string, object?>();
|
|
foreach (var (key, propSchema) in schema.Properties)
|
|
{
|
|
obj[key] = Generate(propSchema, doc, depth + 1, seen);
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static object MockString(string? format) => format switch
|
|
{
|
|
"date-time" => DateTime.UtcNow.ToString("O"),
|
|
"date" => DateOnly.FromDateTime(DateTime.UtcNow).ToString("yyyy-MM-dd"),
|
|
"time" => TimeOnly.FromDateTime(DateTime.UtcNow).ToString("HH:mm:ss"),
|
|
"uuid" => Guid.NewGuid().ToString(),
|
|
"uri" => "https://example.com/resource",
|
|
_ => "string"
|
|
};
|
|
|
|
private static int RandomInt(int depth) => 1 + depth;
|
|
}
|
|
} |