diff --git a/.github/workflows/test-pr.yaml b/.github/workflows/test-pr.yaml
index 0e53ae7b11..c86dd82db4 100644
--- a/.github/workflows/test-pr.yaml
+++ b/.github/workflows/test-pr.yaml
@@ -123,7 +123,7 @@ jobs:
if: ${{ contains(matrix.fixture, 'csharp') }}
uses: actions/setup-dotnet@v3
with:
- dotnet-version: 6
+ dotnet-version: 8
- name: Install Rust
if: ${{ contains(matrix.fixture, 'rust') }}
diff --git a/packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts
index 8dd10334da..3e331a310b 100644
--- a/packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts
+++ b/packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts
@@ -188,7 +188,7 @@ export class CSharpRenderer extends ConvenienceRenderer {
): Sourcelike {
t = followTargetType(t);
const csType = this.csType(t, follow, withIssues);
- if (isValueType(t)) {
+ if (isValueType(t) || this._csOptions.version >= 8) {
return [csType, "?"];
} else {
return csType;
diff --git a/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts
index c69107ebd9..1993f6e135 100644
--- a/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts
+++ b/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts
@@ -192,6 +192,15 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer {
return this._options.baseclass;
}
+ protected emitDefaultFollowingComments(): void {
+ if (!this._needHelpers || this._options.version < 8) return;
+
+ this.emitLine("#pragma warning restore CS8618");
+ this.emitLine("#pragma warning restore CS8601");
+ this.emitLine("#pragma warning restore CS8603");
+ this.emitLine("#pragma warning restore CS8765");
+ }
+
protected emitDefaultLeadingComments(): void {
if (!this._needHelpers) return;
@@ -225,6 +234,14 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer {
";",
);
});
+
+ if (this._options.version >= 8) {
+ this.emitLine("#nullable enable");
+ this.emitLine("#pragma warning disable CS8618");
+ this.emitLine("#pragma warning disable CS8601");
+ this.emitLine("#pragma warning disable CS8603");
+ this.emitLine("#pragma warning disable CS8765");
+ }
}
private converterForType(t: Type): Name | undefined {
diff --git a/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts
index 34204577b4..e64a915dcb 100644
--- a/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts
+++ b/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts
@@ -275,6 +275,13 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer {
const isNullable = followTargetType(property.type).isNullable;
const isOptional = property.isOptional;
+ // [JsonRequired] makes deserialization fail if the property is
+ // missing from the JSON. It requires System.Text.Json 7.0 or
+ // later (.NET 7+).
+ if (this._options.checkRequired && !isOptional) {
+ attributes.push(["[JsonRequired]"]);
+ }
+
if (isOptional && !isNullable) {
attributes.push([
"[",
diff --git a/packages/quicktype-core/src/language/CSharp/language.ts b/packages/quicktype-core/src/language/CSharp/language.ts
index 0b0c7235f5..b7447d7329 100644
--- a/packages/quicktype-core/src/language/CSharp/language.ts
+++ b/packages/quicktype-core/src/language/CSharp/language.ts
@@ -69,6 +69,7 @@ export const cSharpOptions = {
{
"5": 5,
"6": 6,
+ "8": 8,
} as const,
"6",
"secondary",
diff --git a/test/fixtures/csharp-SystemTextJson/test.csproj b/test/fixtures/csharp-SystemTextJson/test.csproj
index 1f5224ffd3..37d7e4c935 100755
--- a/test/fixtures/csharp-SystemTextJson/test.csproj
+++ b/test/fixtures/csharp-SystemTextJson/test.csproj
@@ -1,9 +1,9 @@
Exe
- net6
+ net8.0
-
+
diff --git a/test/fixtures/csharp/test.csproj b/test/fixtures/csharp/test.csproj
index 2fbf1477c5..9b3c4614b1 100755
--- a/test/fixtures/csharp/test.csproj
+++ b/test/fixtures/csharp/test.csproj
@@ -1,7 +1,7 @@
Exe
- netcoreapp6.0
+ net8.0
diff --git a/test/languages.ts b/test/languages.ts
index 94f9828e3a..7403fce71f 100644
--- a/test/languages.ts
+++ b/test/languages.ts
@@ -118,6 +118,7 @@ export const CSharpLanguage: Language = {
quickTestRendererOptions: [
{ "array-type": "list" },
{ "csharp-version": "5" },
+ { "csharp-version": "8" },
{ density: "dense" },
{ "number-type": "decimal" },
{ "any-type": "dynamic" },
@@ -160,14 +161,12 @@ export const CSharpLanguageSystemTextJson: Language = {
"minmaxlength.schema", // generated converter triggers CS8602 warnings, which "dotnet run" prints to stdout, breaking the JSON comparison
"optional-constraints.schema", // same CS8602 stdout issue; also min/max on integers and pattern on optional strings aren't checked, so expected-failure samples don't fail
"optional-const-ref.schema", // same CS8602 stdout issue; also min/max on integers isn't checked, so the expected-failure sample doesn't fail
- "required.schema", // the renderer doesn't implement check-required, so the expected-failure sample doesn't fail
- "strict-optional.schema", // the renderer doesn't implement check-required, so the expected-failure sample doesn't fail
- "intersection.schema", // the renderer doesn't implement check-required, so the expected-failure sample doesn't fail
],
rendererOptions: { "check-required": "true", framework: "SystemTextJson" },
quickTestRendererOptions: [
{ "array-type": "list" },
{ "csharp-version": "6" },
+ { "csharp-version": "8" },
{ density: "dense" },
{ "number-type": "decimal" },
{ "any-type": "dynamic" },