/system-text-json-net11
Imperative guidance for the System.Text.Json APIs added in .NET 11: the built-in `JsonNamingPolicy.PascalCase` naming policy, and the strongly-typed `JsonSerializerOptions.GetTypeInfo<T>()` and `JsonSerializerOptions.TryGetTypeInfo<T>(out JsonTypeInfo<T>? info)` metadata
$ npx -y skills add dotnet/skills --skill system-text-json-net11 --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/system-text-json-net11
Context preview
The summary Claude sees to decide when to auto-load this skill.
Imperative guidance for the System.Text.Json APIs added in .NET 11: the built-in `JsonNamingPolicy.PascalCase` naming policy, and the strongly-typed `JsonSerializerOptions.GetTypeInfo<T>()` and `JsonSerializerOptions.TryGetTypeInfo<T>(out JsonTypeInfo<T>? info)` metadata
SKILL.md
system-text-json-net11.SKILL.mdname: system-text-json-net11
description: >
Imperative guidance for the System.Text.Json APIs added in .NET 11: the built-in
`JsonNamingPolicy.PascalCase` naming policy, and the strongly-typed
`JsonSerializerOptions.GetTypeInfo<T>()` and
`JsonSerializerOptions.TryGetTypeInfo<T>(out JsonTypeInfo<T>? info)`
metadata accessors.
USE FOR: serializing or deserializing JSON in a net11.0-or-later project when you need
PascalCase JSON property names without writing a custom naming policy, a strongly-typed
`JsonTypeInfo<T>` instead of the non-generic `JsonTypeInfo`, or a no-throw way to probe
whether a type's serialization metadata is resolved.
DO NOT USE FOR: projects targeting net10.0 or earlier (none of these APIs exist there),
JSON libraries other than System.Text.Json (e.g. Newtonsoft.Json), or camelCase /
snake_case / kebab-case naming — those policies shipped in earlier releases.
license: MIT
System.Text.Json — .NET 11
Three APIs were added to `System.Text.Json` in .NET 11. This skill tells you exactly when to reach for each one, what to write, what **not** to write, and how to prove the result runs. Do not describe these APIs to the user — apply them, then run the code and show the output.
| API | Replaces the pre-.NET-11 workaround of... | | --- | --- | | `JsonNamingPolicy.PascalCase` (static property) | writing a custom `JsonNamingPolicy` subclass or hand-annotating every member with `[JsonPropertyName]` | | `JsonSerializerOptions.GetTypeInfo<T>()` | calling non-generic `GetTypeInfo(typeof(T))` and casting to `JsonTypeInfo<T>` | | `JsonSerializerOptions.TryGetTypeInfo<T>(out JsonTypeInfo<T>? info)` | wrapping `GetTypeInfo` in `try`/`catch` to probe availability |
Step 0 — Confirm you can target .NET 11
These APIs only exist in the .NET 11 base class library. Before writing code:
1. Run `dotnet --list-sdks` and confirm an SDK that can target `net11.0` is present — an `11.x` SDK, or any later SDK (`12.x`+) that has the `net11.0` targeting pack installed. 2. If no such SDK is available, **stop**: tell the user these APIs require targeting `net11.0` (on the .NET 11 SDK or later) and cannot compile on `net10.0` or earlier. Do not fall back to a custom implementation and pretend it is the new API.
Decision table — symptom → do this → never do this
Match the user's request to a row, apply the **Do this** cell verbatim, and confirm the **Verify** column before you are done.
| User asks for… | Do this (on `net11.0`) | Never do this | Verify | | --- | --- | --- | --- | | PascalCase JSON property names | `options.PropertyNamingPolicy = JsonNamingPolicy.PascalCase;` | define `class …: JsonNamingPolicy`; add per-member `[JsonPropertyName]`; string-case the names yourself | output JSON keys are PascalCase — e.g. `"Name"`, `"Age"` | | Strongly-typed metadata `JsonTypeInfo<T>` | set `TypeInfoResolver = new DefaultJsonTypeInfoResolver()`, then `JsonTypeInfo<T> ti = options.GetTypeInfo<T>();` | `(JsonTypeInfo<T>)options.GetTypeInfo(typeof(T))` | variable is typed `JsonTypeInfo<T>`, no cast | | Probe whether metadata is resolved | `if (options.TryGetTypeInfo<T>(out var ti)) { … } else { … }` | `try { options.GetTypeInfo<T>(); } catch (…) { … }` | no `try`/`catch`; both branches handled |
Rule 1 — PascalCase property names
**When** the user wants JSON output whose property names are PascalCase (`Name`, `Age`) and asks for the built-in / framework-provided way:
1. Create or reuse a `JsonSerializerOptions` and set `PropertyNamingPolicy = JsonNamingPolicy.PascalCase`. 2. Serialize with those options.
Do **not** write a `JsonNamingPolicy` subclass, do **not** add `[JsonPropertyName("…")]` attributes to force casing, and do **not** upper-case the first letter of each name by hand. `JsonNamingPolicy.PascalCase` is the single correct answer on .NET 11.
// Console project (reflection enabled by default). To run this as a file-based app
// (dotnet run app.cs), also set TypeInfoResolver = new DefaultJsonTypeInfoResolver()
// — see "Producing runnable output" below.
using System.Text.Json;
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.PascalCase
};
string json = JsonSerializer.Serialize(new { name = "Jane", age = 30 }, options);
Console.WriteLine(json);
// {"Name":"Jane","Age":30}Rule 2 — Strongly-typed `JsonTypeInfo<T>`
**When** the user wants type metadata back as `JsonTypeInfo<T>` (not the non-generic `JsonTypeInfo` that needs a cast):
1. Call `options.GetTypeInfo<T>()` — it returns `JsonTypeInfo<T>` directly. 2. Assign it to a `JsonTypeInfo<T>` variable and use it (e.g. pass it to `JsonSerializer.Serialize`/`Deserialize`).
Do **not** call the non-generic `GetTypeInfo(Type)` overload and cast the result.
> **Requires a resolver.** `GetTypeInfo<T>()` throws `NotSupportedException` > (`NoMetadataForType`) unless the options have a `TypeInfoResolver` — set > `TypeInfoResolver = new DefaultJsonTypeInfoResolver()` for reflection-based apps, or use > a source-generated `JsonSerializerContext` for trimmed/AOT apps.
// File-based app (run: dotnet run app.cs). In a .csproj project, remove this line and
// set <TargetFramework>net11.0</TargetFramework> in the project file instead.
#:property TargetFramework=net11.0
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
var options = new JsonSerializerOptions
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
};
JsonTypeInfo<Person> typeInfo = options.GetTypeInfo<Person>();
Console.WriteLine(typeInfo.Type.Name); // Person
record Person(string Name, int Age);Rule 3 — Probe metadata without throwing
**When** the user wants to check whether metadata for `T` is available and branch on it — *without* an exception being thrown when it is not:
1. Call `options.TryGetTypeInfo<T>(out var info)`. 2. Handle the `true` branch (metadata resolved, use `info`) and the `false` branch (not resolved) explici
Read more
name: system-text-json-net11 description: > Imperative guidance for the System.Text.Json APIs added in .NET 11: the built-in `JsonNamingPolicy.PascalCase` naming policy, and the strongly-typed `JsonSerializerOptions.GetTypeInfo<T>()` and `JsonSerializerOptions.TryGetTypeInfo<T>(out JsonTypeInfo<T>? info)` metadata accessors. USE FOR: serializing or deserializing JSON in a net11.0-or-later project when you need PascalCase JSON property names without writing a custom naming policy, a strongly-typed `JsonTypeInfo<T>` instead of the non-generic `JsonTypeInfo`, or a no-throw way to probe whether a type's serialization metadata is resolved. DO NOT USE FOR: projects targeting net10.0 or earlier (none of these APIs exist there), JSON libraries other than System.Text.Json (e.g. Newtonsoft.Json), or camelCase / snake_case / kebab-case naming — those policies shipped in earlier releases. license: MIT
System.Text.Json — .NET 11
Three APIs were added to `System.Text.Json` in .NET 11. This skill tells you exactly when to reach for each one, what to write, what **not** to write, and how to prove the result runs. Do not describe these APIs to the user — apply them, then run the code and show the output.
| API | Replaces the pre-.NET-11 workaround of... | | --- | --- | | `JsonNamingPolicy.PascalCase` (static property) | writing a custom `JsonNamingPolicy` subclass or hand-annotating every member with `[JsonPropertyName]` | | `JsonSerializerOptions.GetTypeInfo<T>()` | calling non-generic `GetTypeInfo(typeof(T))` and casting to `JsonTypeInfo<T>` | | `JsonSerializerOptions.TryGetTypeInfo<T>(out JsonTypeInfo<T>? info)` | wrapping `GetTypeInfo` in `try`/`catch` to probe availability |
Step 0 — Confirm you can target .NET 11
These APIs only exist in the .NET 11 base class library. Before writing code:
1. Run `dotnet --list-sdks` and confirm an SDK that can target `net11.0` is present — an `11.x` SDK, or any later SDK (`12.x`+) that has the `net11.0` targeting pack installed. 2. If no such SDK is available, **stop**: tell the user these APIs require targeting `net11.0` (on the .NET 11 SDK or later) and cannot compile on `net10.0` or earlier. Do not fall back to a custom implementation and pretend it is the new API.
Decision table — symptom → do this → never do this
Match the user's request to a row, apply the **Do this** cell verbatim, and confirm the **Verify** column before you are done.
| User asks for… | Do this (on `net11.0`) | Never do this | Verify | | --- | --- | --- | --- | | PascalCase JSON property names | `options.PropertyNamingPolicy = JsonNamingPolicy.PascalCase;` | define `class …: JsonNamingPolicy`; add per-member `[JsonPropertyName]`; string-case the names yourself | output JSON keys are PascalCase — e.g. `"Name"`, `"Age"` | | Strongly-typed metadata `JsonTypeInfo<T>` | set `TypeInfoResolver = new DefaultJsonTypeInfoResolver()`, then `JsonTypeInfo<T> ti = options.GetTypeInfo<T>();` | `(JsonTypeInfo<T>)options.GetTypeInfo(typeof(T))` | variable is typed `JsonTypeInfo<T>`, no cast | | Probe whether metadata is resolved | `if (options.TryGetTypeInfo<T>(out var ti)) { … } else { … }` | `try { options.GetTypeInfo<T>(); } catch (…) { … }` | no `try`/`catch`; both branches handled |
Rule 1 — PascalCase property names
**When** the user wants JSON output whose property names are PascalCase (`Name`, `Age`) and asks for the built-in / framework-provided way:
1. Create or reuse a `JsonSerializerOptions` and set `PropertyNamingPolicy = JsonNamingPolicy.PascalCase`. 2. Serialize with those options.
Do **not** write a `JsonNamingPolicy` subclass, do **not** add `[JsonPropertyName("…")]` attributes to force casing, and do **not** upper-case the first letter of each name by hand. `JsonNamingPolicy.PascalCase` is the single correct answer on .NET 11.
// Console project (reflection enabled by default). To run this as a file-based app
// (dotnet run app.cs), also set TypeInfoResolver = new DefaultJsonTypeInfoResolver()
// — see "Producing runnable output" below.
using System.Text.Json;
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.PascalCase
};
string json = JsonSerializer.Serialize(new { name = "Jane", age = 30 }, options);
Console.WriteLine(json);
// {"Name":"Jane","Age":30}Rule 2 — Strongly-typed `JsonTypeInfo<T>`
**When** the user wants type metadata back as `JsonTypeInfo<T>` (not the non-generic `JsonTypeInfo` that needs a cast):
1. Call `options.GetTypeInfo<T>()` — it returns `JsonTypeInfo<T>` directly. 2. Assign it to a `JsonTypeInfo<T>` variable and use it (e.g. pass it to `JsonSerializer.Serialize`/`Deserialize`).
Do **not** call the non-generic `GetTypeInfo(Type)` overload and cast the result.
> **Requires a resolver.** `GetTypeInfo<T>()` throws `NotSupportedException` > (`NoMetadataForType`) unless the options have a `TypeInfoResolver` — set > `TypeInfoResolver = new DefaultJsonTypeInfoResolver()` for reflection-based apps, or use > a source-generated `JsonSerializerContext` for trimmed/AOT apps.
// File-based app (run: dotnet run app.cs). In a .csproj project, remove this line and
// set <TargetFramework>net11.0</TargetFramework> in the project file instead.
#:property TargetFramework=net11.0
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
var options = new JsonSerializerOptions
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
};
JsonTypeInfo<Person> typeInfo = options.GetTypeInfo<Person>();
Console.WriteLine(typeInfo.Type.Name); // Person
record Person(string Name, int Age);Rule 3 — Probe metadata without throwing
**When** the user wants to check whether metadata for `T` is available and branch on it — *without* an exception being thrown when it is not:
1. Call `options.TryGetTypeInfo<T>(out var info)`. 2. Handle the `true` branch (metadata resolved, use `info`) and the `false` branch (not resolved) explici
This repository contains the .NET team's curated set of core skills and custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io. 📊 Dashboard - Accuracy and efficiency scoring trends for contained plugins (
Repo: dotnet/skills
Other skills on dotnet-skills.
- /csharp-scripts
Run file-based C# apps with the .NET CLI when the user explicitly wants C#/.NET code without creating a project. Use for C# language/API experiments, one-file C# apps, small multi-file C# apps composed with `#:include`/`#:exclude`, or C# file-based apps linked with `#:ref`. Do
Open skill - /dotnet-pinvoke
Correctly call native (C/C++) libraries from .NET using P/Invoke and LibraryImport. Covers function signatures, string marshalling, memory lifetime, SafeHandle, and cross-platform patterns. USE FOR: writing new P/Invoke or LibraryImport declarations, reviewing or debugging
Open skill - /nuget-trusted-publishing
Set up NuGet trusted publishing (OIDC) on a GitHub Actions repo — replaces long-lived API keys with short-lived tokens. USE FOR: trusted publishing, NuGet OIDC, keyless NuGet publish, migrate from NuGet API key, NuGet/login, secure NuGet publishing. DO NOT USE FOR: publishing to
Open skill - /technology-selection
Guides technology selection and implementation of AI and ML features in .NET 8+ applications using ML.NET, Microsoft.Extensions.AI (MEAI), Microsoft Agent Framework (MAF), GitHub Copilot SDK, ONNX Runtime, and OllamaSharp. Covers the full spectrum from classic ML through modern
Open skill - /configuring-opentelemetry-dotnet
Configure OpenTelemetry distributed tracing, metrics, and logging in ASP.NET Core using the .NET OpenTelemetry SDK. Use when adding observability, setting up OTLP exporters, creating custom metrics/spans, or troubleshooting distributed trace correlation.
Open skill - /convert-blazor-server-to-webapp
Guides conversion of a pre-.NET 8 Blazor Server app into a .NET 8+ Blazor Web App. USE FOR: migrating apps that use AddServerSideBlazor and MapBlazorHub to the AddRazorComponents/MapRazorComponents model, converting _Host.cshtml to an App.razor root component, replacing
Open skill

