JSON-schemaexporteur
Met de JsonSchemaExporter klasse, geïntroduceerd in .NET 9, kunt u JSON-schemadocumenten uit .NET-typen extraheren met behulp van een of JsonTypeInfo meer JsonSerializerOptions exemplaren. Het resulterende schema bevat een specificatie van het JSON-serialisatiecontract voor het .NET-type. In het schema wordt de vorm beschreven van wat er geserialiseerd zou worden en wat kan worden gedeserialiseerd.
In het volgende codefragment ziet u een voorbeeld.
public static void SimpleExtraction()
{
JsonSerializerOptions options = JsonSerializerOptions.Default;
JsonNode schema = options.GetJsonSchemaAsNode(typeof(Person));
Console.WriteLine(schema.ToString());
//{
// "type": ["object", "null"],
// "properties": {
// "Name": { "type": "string" },
// "Age": { "type": "integer" },
// "Address": { "type": ["string", "null"], "default": null }
// },
// "required": ["Name", "Age"]
//}
}
record Person(string Name, int Age, string? Address = null);
Zoals in dit voorbeeld te zien is, maakt de exporteur onderscheid tussen nullable en niet-nullable eigenschappen en wordt het required
trefwoord ingevuld op grond van een constructorparameter die optioneel is of niet.
De schema-uitvoer configureren
U kunt de schema-uitvoer beïnvloeden door de configuratie die is opgegeven in het JsonSerializerOptions of JsonTypeInfo exemplaar waarop u de GetJsonSchemaAsNode methode aanroept. In het volgende voorbeeld wordt het naamgevingsbeleid KebabCaseUpperingesteld op, worden getallen als tekenreeksen geschreven en worden niet-toegewezen eigenschappen niet toegedeeld.
public static void CustomExtraction()
{
JsonSerializerOptions options = new(JsonSerializerOptions.Default)
{
PropertyNamingPolicy = JsonNamingPolicy.KebabCaseUpper,
NumberHandling = JsonNumberHandling.WriteAsString,
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,
};
JsonNode schema = options.GetJsonSchemaAsNode(typeof(MyPoco));
Console.WriteLine(schema.ToString());
//{
// "type": ["object", "null"],
// "properties": {
// "NUMERIC-VALUE": {
// "type": ["string", "integer"],
// "pattern": "^-?(?:0|[1-9]\\d*)$"
// }
// },
// "additionalProperties": false
//}
}
class MyPoco
{
public int NumericValue { get; init; }
}
U kunt het gegenereerde schema verder beheren met behulp van het JsonSchemaExporterOptions configuratietype. In het volgende voorbeeld wordt de TreatNullObliviousAsNonNullable eigenschap ingesteld om true
typen op hoofdniveau te markeren als niet-nullable.
public static void CustomExtraction()
{
JsonSerializerOptions options = JsonSerializerOptions.Default;
JsonSchemaExporterOptions exporterOptions = new()
{
TreatNullObliviousAsNonNullable = true,
};
JsonNode schema = options.GetJsonSchemaAsNode(typeof(Person), exporterOptions);
Console.WriteLine(schema.ToString());
//{
// "type": "object",
// "properties": {
// "Name": { "type": "string" }
// },
// "required": ["Name"]
//}
}
record Person(string Name);
Het gegenereerde schema transformeren
U kunt uw eigen transformaties toepassen op gegenereerde schemaknooppunten door een TransformSchemaNode gemachtigde op te geven. In het volgende voorbeeld wordt tekst uit DescriptionAttribute aantekeningen opgenomen in het gegenereerde schema.
JsonSchemaExporterOptions exporterOptions = new()
{
TransformSchemaNode = (context, schema) =>
{
// Determine if a type or property and extract the relevant attribute provider.
ICustomAttributeProvider? attributeProvider = context.PropertyInfo is not null
? context.PropertyInfo.AttributeProvider
: context.TypeInfo.Type;
// Look up any description attributes.
DescriptionAttribute? descriptionAttr = attributeProvider?
.GetCustomAttributes(inherit: true)
.Select(attr => attr as DescriptionAttribute)
.FirstOrDefault(attr => attr is not null);
// Apply description attribute to the generated schema.
if (descriptionAttr != null)
{
if (schema is not JsonObject jObj)
{
// Handle the case where the schema is a Boolean.
JsonValueKind valueKind = schema.GetValueKind();
Debug.Assert(valueKind is JsonValueKind.True or JsonValueKind.False);
schema = jObj = new JsonObject();
if (valueKind is JsonValueKind.False)
{
jObj.Add("not", true);
}
}
jObj.Insert(0, "description", descriptionAttr.Description);
}
return schema;
}
};
In het volgende codevoorbeeld wordt een schema gegenereerd dat een trefwoordbron uit DescriptionAttribute aantekeningen bevatdescription
:
JsonSerializerOptions options = JsonSerializerOptions.Default;
JsonNode schema = options.GetJsonSchemaAsNode(typeof(Person), exporterOptions);
Console.WriteLine(schema.ToString());
//{
// "description": "A person",
// "type": ["object", "null"],
// "properties": {
// "Name": { "description": "The name of the person", "type": "string" }
// },
// "required": ["Name"]
//}
[Description("A person")]
record Person([property: Description("The name of the person")] string Name);