ktsu.Schema
1.10.0
Prefix Reserved
dotnet add package ktsu.Schema --version 1.10.0
NuGet\Install-Package ktsu.Schema -Version 1.10.0
<PackageReference Include="ktsu.Schema" Version="1.10.0" />
<PackageVersion Include="ktsu.Schema" Version="1.10.0" />
<PackageReference Include="ktsu.Schema" />
paket add ktsu.Schema --version 1.10.0
#r "nuget: ktsu.Schema, 1.10.0"
#:package ktsu.Schema@1.10.0
#addin nuget:?package=ktsu.Schema&version=1.10.0
#tool nuget:?package=ktsu.Schema&version=1.10.0
ktsu.Schema
A C# library for defining, managing, and editing data structure schemas with a rich type system, type-safe identifiers, and polymorphic JSON serialization.
Overview
ktsu.Schema lets you define structured data models programmatically or visually, then serialize them to .schema.json files (documented in the schema file format reference). It provides a foundation for code generation, data validation, and tooling that needs to understand your data structures at a metadata level.
The solution contains three projects:
- Schema - Core library with schema definition types, a rich type system, and JSON serialization
- Schema.Test - Unit tests for the core library
- SchemaEditor - ImGui-based desktop application for visual schema editing
Installation
Install via NuGet:
dotnet add package ktsu.Schema
Or add to your project file:
<PackageReference Include="ktsu.Schema" />
Requirements
- .NET 8.0, 9.0, or 10.0
Quick Start
Create a Schema
using ktsu.Schema.Models;
using ktsu.Schema.Models.Names;
using ktsu.Schema.Models.Types;
using ktsu.Semantics.Strings;
using SchemaTypes = ktsu.Schema.Models.Types;
// Create a new schema
Schema schema = new();
// Add an enum
SchemaEnum? roleEnum = schema.AddEnum("UserRole".As<EnumName>());
roleEnum?.TryAddValue("Admin".As<EnumValueName>());
roleEnum?.TryAddValue("User".As<EnumValueName>());
roleEnum?.TryAddValue("Guest".As<EnumValueName>());
// Add a class with typed members
SchemaClass? userClass = schema.AddClass("User".As<ClassName>());
if (userClass != null)
{
SchemaMember? id = userClass.AddMember("Id".As<MemberName>());
id?.SetType(new SchemaTypes.Int());
SchemaMember? name = userClass.AddMember("Name".As<MemberName>());
name?.SetType(new SchemaTypes.String());
SchemaMember? email = userClass.AddMember("Email".As<MemberName>());
email?.SetType(new SchemaTypes.String());
SchemaMember? role = userClass.AddMember("Role".As<MemberName>());
role?.SetType(new SchemaTypes.Enum { EnumName = "UserRole".As<EnumName>() });
SchemaMember? createdAt = userClass.AddMember("CreatedAt".As<MemberName>());
createdAt?.SetType(new SchemaTypes.DateTime());
}
Work with Arrays and Object References
// Add a Project class
SchemaClass? projectClass = schema.AddClass("Project".As<ClassName>());
SchemaMember? projectId = projectClass?.AddMember("Id".As<MemberName>());
projectId?.SetType(new SchemaTypes.Int());
SchemaMember? projectName = projectClass?.AddMember("Name".As<MemberName>());
projectName?.SetType(new SchemaTypes.String());
// Add an array of projects to the User class
SchemaMember? projects = userClass?.AddMember("Projects".As<MemberName>());
projects?.SetType(new SchemaTypes.Array
{
ElementType = new SchemaTypes.Object { ClassName = "Project".As<ClassName>() },
Container = "vector".As<ContainerName>()
});
// Use a keyed collection (map)
SchemaMember? projectsMap = userClass?.AddMember("ProjectsById".As<MemberName>());
projectsMap?.SetType(new SchemaTypes.Array
{
ElementType = new SchemaTypes.Object { ClassName = "Project".As<ClassName>() },
Container = "map".As<ContainerName>(),
Key = "Id".As<MemberName>()
});
Create a Schema from .NET Types
// Generate a schema class from an existing .NET type using reflection
schema.AddClass(typeof(MyExistingClass));
Serialize and Deserialize
// Serialize to JSON
string json = SchemaSerializer.Serialize(schema);
// Deserialize from JSON (automatically calls Reassociate())
if (SchemaSerializer.TryDeserialize(json, out Schema? loaded))
{
Console.WriteLine($"Loaded {loaded.Classes.Count} classes");
}
Query the Schema
// Retrieve classes and enums
if (schema.TryGetClass("User".As<ClassName>(), out SchemaClass? foundClass))
{
foreach (SchemaMember member in foundClass.Members)
{
Console.WriteLine($" {member.Name}: {member.Type.DisplayName}");
}
}
if (schema.TryGetEnum("UserRole".As<EnumName>(), out SchemaEnum? foundEnum))
{
foreach (EnumValueName value in foundEnum.Values)
{
Console.WriteLine($" {value}");
}
}
Type System
The schema supports a rich set of types through the SchemaTypes class, all inheriting from BaseType with polymorphic JSON serialization via System.Text.Json:
| Category | Types |
|---|---|
| Numeric | Int, Long, Float, Double |
| Text | String |
| Logic | Bool |
| Temporal | DateTime, TimeSpan |
| Vectors | Vector2, Vector3, Vector4 |
| Colors | ColorRGB, ColorRGBA |
| Complex | Array, Object, Enum |
| Special | None |
Types expose classification properties like IsPrimitive, IsNumeric, IsIntegral, IsDecimal, IsArray, IsObject, IsContainer, and IsBuiltIn.
Strong String Types
All identifiers use type-safe semantic string wrappers from ktsu.Semantics.Strings to prevent mixing up different kinds of names at compile time:
ClassName- Schema class namesMemberName- Class member namesEnumName- Enumeration namesEnumValueName- Enumeration value namesBaseTypeName- Type namesContainerName- Container type namesDataSourceName- Data source namesCodeGeneratorName- Code generator names
Convert strings using the .As<T>() extension method: "User".As<ClassName>()
JSON Serialization
Use SchemaSerializer for JSON serialization with System.Text.Json. The serializer uses camelCase property names and polymorphic type discrimination via the TypeName discriminator:
{
"classes": [
{
"name": "User",
"description": "",
"members": [
{
"name": "Id",
"description": "",
"type": { "TypeName": "Int" },
"memberDescription": ""
},
{
"name": "Role",
"description": "",
"type": { "TypeName": "Enum", "enumName": "UserRole" },
"memberDescription": ""
}
]
}
],
"enums": [
{
"name": "UserRole",
"description": "",
"values": ["Admin", "User", "Guest"]
}
],
"dataSources": [],
"codeGenerators": []
}
SchemaSerializer.TryDeserialize() automatically calls Reassociate() to re-establish parent-child relationships after deserialization.
Schema Editor
The SchemaEditor is an ImGui-based desktop application for visually creating and editing .schema.json files.
Running the Editor
dotnet run --project SchemaEditor
Features
- Tree view for navigating classes, enums, data sources, and code generators
- Property panels for editing members and types
- Type selection dialogs
- Create, open, and save schema files
- Resizable split-panel layout with persistent settings
Building
Building the solution requires the .NET SDK 10.0.400 or newer. This is the floor
pinned in global.json: the analyzers shipped by ktsu.Sdk are built against the
Roslyn version in that feature band, and an older 10.0.x SDK fails the build with
CS9057 before compiling any source. An SDK newer than the floor is fine —
global.json sets rollForward: latestFeature.
# Build the entire solution
dotnet build
# Run tests
dotnet test
# Build a specific project
dotnet build Schema/Schema.csproj
License
This project is licensed under the MIT License. See LICENSE.md for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- ktsu.CodeBlocker (>= 1.3.0)
- ktsu.RoundTripStringJsonConverter (>= 1.0.47)
- ktsu.Semantics.Paths (>= 3.1.4)
- ktsu.Semantics.Strings (>= 3.1.4)
-
net8.0
- ktsu.CodeBlocker (>= 1.3.0)
- ktsu.RoundTripStringJsonConverter (>= 1.0.47)
- ktsu.Semantics.Paths (>= 3.1.4)
- ktsu.Semantics.Strings (>= 3.1.4)
- System.Text.Json (>= 10.0.11)
-
net9.0
- ktsu.CodeBlocker (>= 1.3.0)
- ktsu.RoundTripStringJsonConverter (>= 1.0.47)
- ktsu.Semantics.Paths (>= 3.1.4)
- ktsu.Semantics.Strings (>= 3.1.4)
- System.Text.Json (>= 10.0.11)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.10.0 | 55 | 8/28/2026 |
| 1.9.0 | 49 | 8/27/2026 |
| 1.8.0 | 57 | 8/27/2026 |
| 1.7.10 | 56 | 8/26/2026 |
| 1.7.9 | 59 | 8/25/2026 |
| 1.7.8 | 84 | 8/24/2026 |
| 1.7.7 | 97 | 8/21/2026 |
| 1.7.6 | 91 | 8/20/2026 |
| 1.7.5 | 95 | 8/19/2026 |
| 1.7.4 | 92 | 8/18/2026 |
| 1.7.3 | 101 | 8/17/2026 |
| 1.7.2 | 148 | 6/16/2026 |
| 1.7.1 | 130 | 6/15/2026 |
| 1.7.0 | 114 | 6/14/2026 |
| 1.6.2 | 120 | 6/14/2026 |
| 1.6.1 | 112 | 6/13/2026 |
| 1.6.0 | 121 | 6/13/2026 |
| 1.5.0 | 118 | 6/12/2026 |
| 1.4.1 | 119 | 6/12/2026 |
| 1.4.0 | 134 | 2/10/2026 |
## v1.10.0 (minor)
Changes since v1.9.0:
- Make the models implement the Schema.Contracts abstraction ([@Claude](https://github.com/Claude))