Skip to content

Commit 0b5495d

Browse files
authored
Merge pull request #6 from gregsdennis/corvus
add post about corvus.jsonschema
2 parents 49c9ef6 + 845ca49 commit 0b5495d

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

.jekyll-metadata

2.32 KB
Binary file not shown.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
title: "Dropping Project Support for Code Generation"
3+
date: 2024-02-11 09:00:00 +1200
4+
tags: [json-schema, codegen]
5+
toc: true
6+
pin: false
7+
---
8+
9+
Some time ago, I released [my first attempt at code generation](/posts/exploring-codegen) from JSON Schemas. However, I've decided to deprecate the library in favor of _Corvus.JsonSchema_.
10+
11+
When I created _JsonSchema.Net.CodeGeneration_, I knew about _Corvus.JsonSchema_, but I thought it was merely an alternative validator. I didn't truly understand its approach to supporting JSON Schema in .Net.
12+
13+
Today we're going to take a look at this seeming competitor to see why it actually isn't one.
14+
15+
## What is _Corvus.JsonSchema_?
16+
17+
_Corvus.JsonSchema_ is a JSON Schema code generator that bakes validation logic directly into the model.
18+
19+
To show this, consider the following schema.
20+
21+
```json
22+
{
23+
"type": "object",
24+
"properties": {
25+
"foo": {
26+
"type": "integer",
27+
"minimum": 0
28+
}
29+
}
30+
}
31+
```
32+
33+
As one would expect, the library would generate a class with a single property: `int Foo`. But it also generates an `.IsValid()` method that contains all of the validation logic. So if you set `model.Foo = -1`, the `.IsValid()` method will return false.
34+
35+
However _Corvus.JsonSchema_ has another trick up its sleeve. But before we get into that, it will help to have some understanding of how _System.Text.Json_'s `JsonElement` works.
36+
37+
## A quick review of `JsonElement`
38+
39+
Under the hood, `JsonElement` captures the portion of the parsed JSON text by using spans. This has a number of follow-on benefits:
40+
41+
- By avoiding substringing, there are no additional heap allocations.
42+
- `JsonElement` can be a struct, which further avoids allocations, because it only maintains references to existing memory.
43+
- By holding onto the original text, the value can be interpreted different ways. For example, numbers could be read as `double` or `decimal` or `integer`.
44+
45+
As an example, consider this string:
46+
47+
```json
48+
{ "foo": 42, "bar": [ "a string", false ] }
49+
```
50+
51+
Five different `JsonElement`s would be created:
52+
53+
- top-level object
54+
- number value under `foo`
55+
- array value under `bar`
56+
- first element of `bar` array
57+
- second element of `bar` array
58+
59+
But the kicker is that everything simply references the original string.
60+
61+
|Value|Backing span|
62+
|:-|:-|
63+
| top-level object | start: 0, length: 44 |
64+
| number value under `foo` | start: 9, length: 2 |
65+
| array value under `bar` | start: 20, length: 21 |
66+
| first element of `bar` array | start: 22, length: 10 |
67+
| second element of `bar` array | start: 34, length: 5 |
68+
69+
## Back to the validator
70+
71+
_Corvus.JsonSchema_ builds on this "backing data" pattern that `JsonElement` establishes. Instead of creating a backing field that is the same type that the property exposes, which is the traditional approach for backing fields, the generated code will use a `JsonElement` for the backing field while the property is still strongly typed.
72+
73+
This means that a model generated by the library can usually be deserialized without any extra allocations, resulting in very high performance!
74+
75+
> For a much better explanation of what's going on inside the package than what I can provide, I recommend you watch their [showcase video](https://www.youtube.com/watch?v=aTcD-axJBac).
76+
{: .prompt-tip }
77+
78+
## Keep moving forward
79+
80+
Ever since I saw that video, I've lamented the fact that it's only available as a `dotnet` tool. I've always envisioned this functionality as a Roslyn source generator.
81+
82+
To that end, I've paired with [Matthew Adams](https://github.com/mwadams), one of the primary contributors to _Corvus.JsonSchema_, as co-mentor on a [project proposal](https://github.com/json-schema-org/community/issues/614) for JSON Schema's submission to Google's Summer of Code. This project aims to wrap the existing library in an incremental source generator that uses JSON Schema files within a .Net project to automatically generate models at compile time.
83+
84+
This is a great opportunity to learn about incremental source generators in .Net and build your open source portfolio. If this sounds like a fun project, please make your interest known by commenting on the proposal issue linked above.
85+
86+
(Even if it's not accepted by GSoc, we're probably going to do it anyway.)

0 commit comments

Comments
 (0)