|
4 | 4 | JSON Schema is typically itself represented in JSON. To support this, the `JsonSchema`
|
5 | 5 | type is completely compatible with the _System.Text.Json_ serializer.
|
6 | 6 | docs: 'schema/basics/#schema-deserialization'
|
7 |
| - title: Deserializing a schema |
| 7 | + title: Deserializing a Schema |
8 | 8 | instructions: |
|
9 | 9 | Deserialize the text in `schemaText` into a `JsonSchema` variable called `schema`.
|
10 | 10 | inputTemplate: ''
|
11 | 11 | contextCode: |-
|
12 |
| - using System; |
13 |
| - using System.Collections.Generic; |
14 | 12 | using System.Text.Json;
|
15 | 13 | using System.Text.Json.Nodes;
|
16 |
| - using System.Text.Json.Serialization; |
17 | 14 | using Json.Schema;
|
18 | 15 |
|
19 | 16 | namespace LearnJsonEverything;
|
|
65 | 62 | `JsonSchema` and `EvaluationOptions` to your serializer context in order to support
|
66 | 63 | source generation.
|
67 | 64 | docs: 'schema/basics/#aot'
|
68 |
| - title: Deserializing a schema (AOT) |
| 65 | + title: Deserializing a Schema (AOT) |
69 | 66 | instructions: |
|
70 | 67 | Create a serializer context class called `MySerializerContext` and add the appropriate
|
71 | 68 | attributes.
|
72 | 69 | inputTemplate: ''
|
73 | 70 | contextCode: |-
|
74 |
| - using System; |
75 |
| - using System.Collections.Generic; |
76 | 71 | using System.Text.Json;
|
77 | 72 | using System.Text.Json.Nodes;
|
78 | 73 | using System.Text.Json.Serialization;
|
|
122 | 117 | - instance: 6.8
|
123 | 118 | isValid: false
|
124 | 119 | - id: 26b6ebca-58e6-4814-86ea-4946d844c9a6
|
125 |
| - title: 'Schema Builder: Any string' |
| 120 | + title: 'Schema Builder: Any String' |
126 | 121 | background: |
|
127 | 122 | The `JsonSchemaBuilder` class provides a type-safe fluent interface for building schemas in code.
|
128 | 123 | Adding a keyword is accomplished by calling the same-name (usually) extension method.
|
|
132 | 127 | Configure the provided `JsonSchemaBuilder` to produce a schema that validates a string instance.
|
133 | 128 | inputTemplate: ''
|
134 | 129 | contextCode: |-
|
135 |
| - using System; |
136 |
| - using System.Collections.Generic; |
137 |
| - using System.Text.Json; |
138 | 130 | using System.Text.Json.Nodes;
|
139 |
| - using System.Text.Json.Serialization; |
140 | 131 | using Json.Schema;
|
141 | 132 |
|
142 | 133 | namespace LearnJsonEverything;
|
|
166 | 157 | - instance: false
|
167 | 158 | isValid: false
|
168 | 159 | - id: 26b6ebca-58e6-4814-86ea-4946d844c9a7
|
169 |
| - title: 'Schema Builder: Number with limits' |
| 160 | + title: 'Schema Builder: Number with Limits' |
170 | 161 | background: |
|
171 | 162 | The `JsonSchemaBuilder` class provides a type-safe fluent interface for building schemas in code.
|
172 | 163 | Adding a keyword is accomplished by calling the same-name (usually) extension method.
|
|
177 | 168 | that is less than or equal to 10 but greater than 0.
|
178 | 169 | inputTemplate: ''
|
179 | 170 | contextCode: |-
|
180 |
| - using System; |
181 | 171 | using System.Collections.Generic;
|
182 |
| - using System.Text.Json; |
183 | 172 | using System.Text.Json.Nodes;
|
184 |
| - using System.Text.Json.Serialization; |
185 | 173 | using Json.Schema;
|
186 | 174 |
|
187 | 175 | namespace LearnJsonEverything;
|
|
234 | 222 | that automatically calls the `.Build()` method so you don't have to.
|
235 | 223 | docs: 'schema/basics/#schema-inlining'
|
236 | 224 | api: api/JsonSchema.Net/JsonSchemaBuilderExtensions
|
237 |
| - title: 'Schema Builder: Nesting schemas' |
| 225 | + title: 'Schema Builder: Nesting Schemas' |
238 | 226 | instructions: |
|
239 | 227 | Configure the provided `JsonSchemaBuilder` to produce a schema that validates a array instance
|
240 | 228 | filled with integers. Ensure that the array has no more than 5 items.
|
241 | 229 | inputTemplate: ''
|
242 | 230 | contextCode: |-
|
243 |
| - using System; |
244 |
| - using System.Collections.Generic; |
245 |
| - using System.Text.Json; |
246 | 231 | using System.Text.Json.Nodes;
|
247 |
| - using System.Text.Json.Serialization; |
248 | 232 | using Json.Schema;
|
249 | 233 |
|
250 | 234 | namespace LearnJsonEverything;
|
|
295 | 279 | Configure the evaluation options to enable `format` validation.
|
296 | 280 | inputTemplate: ''
|
297 | 281 | contextCode: |-
|
298 |
| - using System; |
299 |
| - using System.Collections.Generic; |
300 |
| - using System.Text.Json; |
301 | 282 | using System.Text.Json.Nodes;
|
302 |
| - using System.Text.Json.Serialization; |
303 | 283 | using Json.Schema;
|
304 | 284 |
|
305 | 285 | namespace LearnJsonEverything;
|
|
381 | 361 | found in the `specVersion` variable.
|
382 | 362 | inputTemplate: ''
|
383 | 363 | contextCode: |-
|
384 |
| - using System; |
385 |
| - using System.Collections.Generic; |
386 | 364 | using System.Text.Json;
|
387 | 365 | using System.Text.Json.Nodes;
|
388 |
| - using System.Text.Json.Serialization; |
389 | 366 | using Json.Schema;
|
390 | 367 | using Json.More;
|
391 | 368 |
|
|
454 | 431 | - instance: ["a string",true,2,4,6,8,4]
|
455 | 432 | version: Draft202012
|
456 | 433 | isValid: true
|
| 434 | +- id: 26b6ebca-58e6-4824-8dea-4946d444c9a8 |
| 435 | + background: | |
| 436 | + Most often you need to ensure that incoming JSON data properly represents the models |
| 437 | + you've created for your application. Often the best way to ensure this is to |
| 438 | + generate schemas directly from those models. |
| 439 | +
|
| 440 | + _JsonSchema.Net.Generation_ provides an additional extension on `JsonSchemaBuilder` |
| 441 | + called `.FromType<T>()`. |
| 442 | + docs: 'schema/schemagen/schema-generation' |
| 443 | + title: 'Generation: Essentials' |
| 444 | + instructions: | |
| 445 | + Configure the builder to generate a schema for the `Person` type. |
| 446 | + inputTemplate: '' |
| 447 | + contextCode: |- |
| 448 | + using System.Text.Json.Nodes; |
| 449 | + using Json.Schema; |
| 450 | + using Json.Schema.Generation; |
| 451 | + |
| 452 | + namespace LearnJsonEverything; |
| 453 | + |
| 454 | + public class Person |
| 455 | + { |
| 456 | + public string FirstName { get; set; } |
| 457 | + public string LastName { get; set; } |
| 458 | + public int Age { get; set; } |
| 459 | + } |
| 460 | +
|
| 461 | + public class Lesson : ILessonRunner<EvaluationResults> |
| 462 | + { |
| 463 | + public EvaluationResults Run(JsonObject test) |
| 464 | + { |
| 465 | + var instance = test["instance"]; |
| 466 | + var builder = new JsonSchemaBuilder(); |
| 467 | +
|
| 468 | + /* USER CODE */ |
| 469 | +
|
| 470 | + var schema = builder.Build(); |
| 471 | + return schema.Evaluate(instance); |
| 472 | + } |
| 473 | + } |
| 474 | + solution: |- |
| 475 | + builder.FromType<Person>(); |
| 476 | + tests: |
| 477 | + - instance: { FirstName: Jane, LastName: Doe, Age: 24 } |
| 478 | + isValid: true |
| 479 | + - instance: { FirstName: Jane } |
| 480 | + isValid: true |
| 481 | + - instance: { FirstName: 24 } |
| 482 | + isValid: false |
| 483 | +- id: 26b6ebca-5de6-4824-8dea-4946d444c9a8 |
| 484 | + background: | |
| 485 | + Most often you need to ensure that incoming JSON data properly represents the models |
| 486 | + you've created for your application. Often the best way to ensure this is to |
| 487 | + generate schemas directly from those models. |
| 488 | +
|
| 489 | + _JsonSchema.Net.Generation_ provides an additional extension on `JsonSchemaBuilder` |
| 490 | + called `.FromType<T>()`. It also provides numerous attributes that can be applied |
| 491 | + to your models in order to create additional constraints in the generated schema. |
| 492 | + docs: 'schema/schemagen/schema-generation#schema-schemagen-best-practices' |
| 493 | + title: 'Generation: More Constraints' |
| 494 | + instructions: | |
| 495 | + Add `FirstName`, `LastName`, and `Age` properties to the `Person` class, and add |
| 496 | + attributes that provide the following constraints: |
| 497 | +
|
| 498 | + - all properties are required |
| 499 | + - `FirstName` and `LastName` must be at least two characters long |
| 500 | + - `Age` must be greater than 0 |
| 501 | + inputTemplate: '' |
| 502 | + contextCode: |- |
| 503 | + using System.Text.Json.Nodes; |
| 504 | + using Json.Schema; |
| 505 | + using Json.Schema.Generation; |
| 506 | + |
| 507 | + namespace LearnJsonEverything; |
| 508 | + |
| 509 | + public class Person |
| 510 | + { |
| 511 | + /* USER CODE */ |
| 512 | + } |
| 513 | +
|
| 514 | + public class Lesson : ILessonRunner<EvaluationResults> |
| 515 | + { |
| 516 | + public EvaluationResults Run(JsonObject test) |
| 517 | + { |
| 518 | + var instance = test["instance"]; |
| 519 | + var builder = new JsonSchemaBuilder().FromType<Person>(); |
| 520 | + var schema = builder.Build(); |
| 521 | + return schema.Evaluate(instance); |
| 522 | + } |
| 523 | + } |
| 524 | + solution: |- |
| 525 | + [Required] |
| 526 | + [MinLength(2)] |
| 527 | + public string FirstName { get; set; } |
| 528 | + [Required] |
| 529 | + [MinLength(2)] |
| 530 | + public string LastName { get; set; } |
| 531 | + [Required] |
| 532 | + [ExclusiveMinimum(0)] |
| 533 | + public int Age { get; set; } |
| 534 | + tests: |
| 535 | + - instance: { FirstName: Jane, LastName: Doe, Age: 24 } |
| 536 | + isValid: true |
| 537 | + - instance: { FirstName: Jane, LastName: Doe } |
| 538 | + isValid: false |
| 539 | + - instance: { FirstName: Jane, Age: 24 } |
| 540 | + isValid: false |
| 541 | + - instance: { LastName: Doe, Age: 24 } |
| 542 | + isValid: false |
| 543 | + - instance: { FirstName: 24 } |
| 544 | + isValid: false |
| 545 | + - instance: { FirstName: J, LastName: Doe, Age: 24 } |
| 546 | + isValid: false |
| 547 | + - instance: { FirstName: Jane, LastName: D, Age: 24 } |
| 548 | + isValid: false |
| 549 | + - instance: { FirstName: Jane, LastName: Doe, Age: -6 } |
| 550 | + isValid: false |
| 551 | +- id: 26b6ebca-5de6-4824-8dea-4a46d444c9a8 |
| 552 | + background: | |
| 553 | + Most often you need to ensure that incoming JSON data properly represents the models |
| 554 | + you've created for your application. Often the best way to ensure this is to |
| 555 | + generate schemas directly from those models. |
| 556 | +
|
| 557 | + _JsonSchema.Net.Generation_ provides an additional extension on `JsonSchemaBuilder` |
| 558 | + called `.FromType<T>()`. It also provides numerous attributes that can be applied |
| 559 | + to your models in order to create additional constraints in the generated schema. |
| 560 | +
|
| 561 | + Nullability works differently in JSON and JSON Schema than it does in .Net. Use |
| 562 | + the `[Nullable()]` attribute to support null values the JSON / JSON Schema way. |
| 563 | + docs: 'schema/schemagen/schema-generation#schema-schemagen-nullability' |
| 564 | + title: 'Generation: Nullability' |
| 565 | + instructions: | |
| 566 | + Add a `DateTime` property called `BirthDate` and mark it as nullable. |
| 567 | + inputTemplate: '' |
| 568 | + contextCode: |- |
| 569 | + using System; |
| 570 | + using System.Text.Json.Nodes; |
| 571 | + using Json.Schema; |
| 572 | + using Json.Schema.Generation; |
| 573 | + |
| 574 | + namespace LearnJsonEverything; |
| 575 | + |
| 576 | + public class Person |
| 577 | + { |
| 578 | + [Required] |
| 579 | + [MinLength(2)] |
| 580 | + public string FirstName { get; set; } |
| 581 | + [Required] |
| 582 | + [MinLength(2)] |
| 583 | + public string LastName { get; set; } |
| 584 | + [Required] |
| 585 | + [ExclusiveMinimum(0)] |
| 586 | + public int Age { get; set; } |
| 587 | +
|
| 588 | + /* USER CODE */ |
| 589 | + } |
| 590 | +
|
| 591 | + public class Lesson : ILessonRunner<EvaluationResults> |
| 592 | + { |
| 593 | + public EvaluationResults Run(JsonObject test) |
| 594 | + { |
| 595 | + var instance = test["instance"]; |
| 596 | + var builder = new JsonSchemaBuilder().FromType<Person>(); |
| 597 | + var schema = builder.Build(); |
| 598 | + // DateTime will generate a `format: date-time` constraint, |
| 599 | + // so we need to be sure to validate the `format` keyword. |
| 600 | + var options = new EvaluationOptions { RequireFormatValidation = true }; |
| 601 | + return schema.Evaluate(instance, options); |
| 602 | + } |
| 603 | + } |
| 604 | + solution: |- |
| 605 | + [Nullable(true)] |
| 606 | + public DateTime? BirthDate { get; set; } |
| 607 | + tests: |
| 608 | + - instance: { FirstName: Jane, LastName: Doe, Age: 24 } |
| 609 | + isValid: true |
| 610 | + - instance: { FirstName: Jane, LastName: Doe, Age: 24, BirthDate: null } |
| 611 | + isValid: true |
| 612 | + - instance: { FirstName: Jane, LastName: Doe, Age: 24, BirthDate: '2000-06-13T00:00:00-06:00' } |
| 613 | + isValid: true |
| 614 | + - instance: { FirstName: Jane, LastName: Doe, Age: 24, BirthDate: '13 June 2000' } |
| 615 | + isValid: false |
| 616 | + - instance: { FirstName: Jane, LastName: Doe, Age: 24, BirthDate: 24 } |
| 617 | + isValid: false |
| 618 | +- id: 26b6ebca-5de6-4824-8dea-4a46d414c9a8 |
| 619 | + background: | |
| 620 | + Most often you need to ensure that incoming JSON data properly represents the models |
| 621 | + you've created for your application. Often the best way to ensure this is to |
| 622 | + generate schemas directly from those models. |
| 623 | +
|
| 624 | + _JsonSchema.Net.Generation_ provides an additional extension on `JsonSchemaBuilder` |
| 625 | + called `.FromType<T>()`. |
| 626 | +
|
| 627 | + Generation will also look for the `<summary>` tag in XML comments to add a `description` |
| 628 | + keyword to your schemas. This is supported on properties and types. |
| 629 | + docs: 'schema/schemagen/schema-generation#schema-schemagen-nullability' |
| 630 | + title: 'Generation: XML Comments' |
| 631 | + instructions: | |
| 632 | + Add some XML comments to the `Person` type to generate a `description` keyword. |
| 633 | + inputTemplate: '' |
| 634 | + contextCode: |- |
| 635 | + using System; |
| 636 | + using System.Text.Json; |
| 637 | + using System.Text.Json.Nodes; |
| 638 | + using Json.Schema; |
| 639 | + using Json.Schema.Generation; |
| 640 | + using Json.More; |
| 641 | + |
| 642 | + namespace LearnJsonEverything; |
| 643 | + |
| 644 | + /* USER CODE */ |
| 645 | + public class Person |
| 646 | + { |
| 647 | + [Required] |
| 648 | + [MinLength(2)] |
| 649 | + public string FirstName { get; set; } |
| 650 | + [Required] |
| 651 | + [MinLength(2)] |
| 652 | + public string LastName { get; set; } |
| 653 | + [Required] |
| 654 | + [ExclusiveMinimum(0)] |
| 655 | + public int Age { get; set; } |
| 656 | + } |
| 657 | +
|
| 658 | + public class Lesson : ILessonRunner<EvaluationResults> |
| 659 | + { |
| 660 | + public EvaluationResults Run(JsonObject test) |
| 661 | + { |
| 662 | + var builder = new JsonSchemaBuilder().FromType<Person>(); |
| 663 | + var schema = builder.Build(); |
| 664 | + var schemaAsNode = JsonSerializer.SerializeToNode(schema); |
| 665 | + |
| 666 | + var metaSchema = new JsonSchemaBuilder() |
| 667 | + .Type(SchemaValueType.Object) |
| 668 | + .Required("description"); |
| 669 | +
|
| 670 | + return metaSchema.Evaluate(schemaAsNode); |
| 671 | + } |
| 672 | + } |
| 673 | + solution: |- |
| 674 | + /// <summary> |
| 675 | + /// This is my summary. It'll end up in a `description` keyword. |
| 676 | + /// </summary> |
| 677 | + tests: |
| 678 | + - instance: null |
| 679 | + isValid: true |
0 commit comments