Strongly-typed C# models for OSCAL (Open Security Controls Assessment Language), generated from NIST Metaschema definitions.
| Package | Description | NuGet | Downloads |
|---|---|---|---|
| DamianH.Oscal | Strongly-typed C# models for OSCAL generated from NIST Metaschema definitions |
- All 8 OSCAL model types — Catalog, Profile, Component Definition, SSP, SAP, SAR, POA&M, and Mapping
- Versioned namespaces —
Oscal.V1_2_0, allowing multiple OSCAL versions to coexist - Zero runtime dependencies — pure models with
System.Text.Jsonsource generation - Modern C# —
sealed recordtypes,requiredproperties,init-only setters,IReadOnlyList<T>collections - High-performance serialization — JSON source generation via
V1_2_0JsonContext
dotnet add package DamianH.OscalRequires .NET 10.0 or later.
using System.Text.Json;
using Oscal.V1_2_0;
// Deserialize using source-generated context (fastest)
var json = File.ReadAllText("nist-800-53-catalog.json");
var catalog = JsonSerializer.Deserialize(json, V1_2_0JsonContext.Default.Catalog);
Console.WriteLine($"Catalog: {catalog.Metadata.Title}");
// Serialize back to JSON
var output = JsonSerializer.Serialize(catalog, V1_2_0JsonContext.Default.Catalog);using System.Text.Json;
using Oscal.V1_2_0;
var catalog = JsonSerializer.Deserialize(json, V1_2_0JsonContext.Default.Catalog);
var profile = JsonSerializer.Deserialize(json, V1_2_0JsonContext.Default.Profile);
var ssp = JsonSerializer.Deserialize(json, V1_2_0JsonContext.Default.SystemSecurityPlan);
var compDef = JsonSerializer.Deserialize(json, V1_2_0JsonContext.Default.ComponentDefinition);
var sap = JsonSerializer.Deserialize(json, V1_2_0JsonContext.Default.AssessmentPlan);
var sar = JsonSerializer.Deserialize(json, V1_2_0JsonContext.Default.AssessmentResults);
var poam = JsonSerializer.Deserialize(json, V1_2_0JsonContext.Default.PlanOfActionAndMilestones);
var mapping = JsonSerializer.Deserialize(json, V1_2_0JsonContext.Default.MappingCollection);using OscalV1_2_0 = Oscal.V1_2_0;
using OscalV1_3_0 = Oscal.V1_3_0; // future
var oldCatalog = JsonSerializer.Deserialize<OscalV1_2_0.Catalog>(oldJson);
var newCatalog = JsonSerializer.Deserialize<OscalV1_3_0.Catalog>(newJson);| OSCAL Version | Namespace | Status |
|---|---|---|
| 1.2.0 | Oscal.V1_2_0 |
Generated |
Reference metaschema definitions are stored for all OSCAL releases from v1.0.0 through v1.2.0.
Models are generated from NIST OSCAL Metaschema XML definitions. Each type is a sealed record:
public sealed record Catalog
{
[JsonPropertyName("uuid")]
public required Guid Uuid { get; init; }
[JsonPropertyName("metadata")]
public required Metadata Metadata { get; init; }
[JsonPropertyName("controls")]
public IReadOnlyList<Control> Controls { get; init; } = [];
[JsonPropertyName("groups")]
public IReadOnlyList<Group> Groups { get; init; } = [];
[JsonPropertyName("back-matter")]
public BackMatter? BackMatter { get; init; }
}JSON serialization uses System.Text.Json source generation with kebab-case naming:
[JsonSourceGenerationOptions(
WriteIndented = true,
PropertyNamingPolicy = JsonKnownNamingPolicy.KebabCaseLower,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(Catalog))]
[JsonSerializable(typeof(Profile))]
// ... all 134 types
public partial class V1_2_0JsonContext : JsonSerializerContext { }dotnet run build.cs # clean + build + test
dotnet run build.cs -- pack # create NuGet packages
dotnet run build.cs -- test # run tests onlydotnet run build.cs -- update-oscal 1.2.0 # fetch specific version
dotnet run build.cs -- update-oscal all # fetch all versionsMIT