Json.Masker.SystemTextJson
0.4.4
See the version list below for details.
dotnet add package Json.Masker.SystemTextJson --version 0.4.4
NuGet\Install-Package Json.Masker.SystemTextJson -Version 0.4.4
<PackageReference Include="Json.Masker.SystemTextJson" Version="0.4.4" />
<PackageVersion Include="Json.Masker.SystemTextJson" Version="0.4.4" />
<PackageReference Include="Json.Masker.SystemTextJson" />
paket add Json.Masker.SystemTextJson --version 0.4.4
#r "nuget: Json.Masker.SystemTextJson, 0.4.4"
#:package Json.Masker.SystemTextJson@0.4.4
#addin nuget:?package=Json.Masker.SystemTextJson&version=0.4.4
#tool nuget:?package=Json.Masker.SystemTextJson&version=0.4.4
Json.Masker
Json.Masker is a simple library mask sensitive values when serializing them to JSON. Mark a property with [Sensitive], flip the ambient masking context on, and the library does the rest—no custom DTOs, no brittle string hacks.
The repository contains the core abstractions plus concrete integrations for both Newtonsoft.Json and System.Text.Json so you can keep your favorite serializer and still get automatic masking.
Packages
| Package | Description |
|---|---|
Json.Masker.Abstract |
Attribute, masking strategies, context accessors, and the default masking service. This transient package isn't published to NuGet; it just keeps the shared bits tidy for the two adapters. |
Json.Masker.Newtonsoft |
Plug-and-play ContractResolver that wraps sensitive members before Newtonsoft writes them out. |
Json.Masker.SystemTextJson |
JsonTypeInfo modifier that swaps in masking converters when the built-in source generator runs. |
All packages version together and ship to NuGet whenever main is updated.
Quick start
Install the package that matches your serializer:
dotnet add package Json.Masker.Newtonsoft
# or
dotnet add package Json.Masker.SystemTextJson
Wire it up
Pick the style that fits your app:
Use the plumbing extension if you're already on
Microsoft.Extensions.DependencyInjection. Callservices.AddJsonMasking()from the matching package and it will register:IMaskingServiceas a singleton, using either the built-inDefaultMaskingServiceor the instance you provide throughMaskingOptions.IJsonMaskingConfiguratoras a singleton, wired to the serializer-specific implementation (NewtonsoftJsonMaskingConfiguratororSystemTextJsonMaskingConfigurator).
Once that extension is in place you can inject
IJsonMaskingConfiguratorwherever you configure the serializer (for example in MVC setup) and let it bolt on the masking bits for you.Wire it manually if you're configuring the serializer yourself or aren't using DI. Just new up
DefaultMaskingService(or your own implementation) and pass it into the resolver/modifier shown in the manual samples below.The options expose a writeable
MaskingServiceproperty, so you can swap in your own masking logic:builder.Services.AddJsonMasking(options => { options.MaskingService = new MyCustomMaskingService(); });
Either way, masking kicks in once you mark your models and flip the context switch.
Mask the model
- Annotate the bits of your model that shouldn't leak.
public sealed class Customer { public string Name { get; set; } = string.Empty; [Sensitive(MaskingStrategy.Creditcard)] public string CreditCard { get; set; } = string.Empty; [Sensitive(MaskingStrategy.Ssn)] public string SSN { get; set; } = string.Empty; [Sensitive] public int Age { get; set; } [Sensitive(MaskingStrategy.Redacted)] public List<string> Hobbies { get; set; } = []; } - Turn masking on for the current request or operation by setting the ambient context (middleware is a great place for this):
MaskingContextAccessor.Set(new MaskingContext { Enabled = true }); - Serialize like normal.
Plumbing extension in action
var builder = WebApplication.CreateBuilder(args);
// using Microsoft.AspNetCore.Mvc;
// using Microsoft.Extensions.DependencyInjection;
// using Microsoft.Extensions.Options;
builder.Services.AddControllers()
.AddNewtonsoftJson();
builder.Services.AddJsonMasking(options =>
{
// Replace with your own IMaskingService if you need custom behavior.
options.MaskingService = new DefaultMaskingService();
});
builder.Services
.AddOptions<MvcNewtonsoftJsonOptions>()
.Configure<IJsonMaskingConfigurator>((opts, configurator) =>
configurator.Configure(opts.SerializerSettings));
var app = builder.Build();
Swap out AddNewtonsoftJson() for the default System.Text.Json stack and tweak the options wiring:
builder.Services.AddControllers();
// using Microsoft.AspNetCore.Http.Json;
// using Microsoft.Extensions.DependencyInjection;
// using Microsoft.Extensions.Options;
builder.Services.AddJsonMasking();
builder.Services
.AddOptions<JsonOptions>()
.Configure<IJsonMaskingConfigurator>((opts, configurator) =>
configurator.Configure(opts.SerializerOptions));
In both cases the extension ensures DI knows about:
- An
IMaskingServicesingleton (default or custom). - An
IJsonMaskingConfiguratorsingleton that knows how to modify the serializer's settings/options.
After that the configurator will plug itself into MVC's JSON settings during startup. You can apply the same pattern to worker services, minimal APIs, or any custom bootstrapping code that uses the Options system.
Manual samples
Newtonsoft.Json
var maskingService = new DefaultMaskingService();
var settings = new JsonSerializerSettings
{
ContractResolver = new MaskingContractResolver(maskingService)
};
var json = JsonConvert.SerializeObject(customer, Formatting.Indented, settings);
Masked output ends up looking like:
{
"Name": "Alice",
"CreditCard": "****-****-****-1234",
"SSN": "***-**-6789",
"Age": "****",
"Hobbies": ["<redacted>", "<redacted>"]
}
System.Text.Json
var maskingService = new DefaultMaskingService();
var options = new JsonSerializerOptions
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { new MaskingTypeInfoModifier(maskingService).Modify }
}
};
var json = JsonSerializer.Serialize(customer, options);
Behind the scenes the modifier swaps in custom converters that call the masking service for both scalars and collections, so you get the same result.
Masking strategies
The built-in DefaultMaskingService supports a few common strategies:
| Strategy | Result |
|---|---|
MaskingStrategy.Default |
**** |
MaskingStrategy.Creditcard |
****-****-****-1234 (keeps the last four digits) |
MaskingStrategy.Ssn |
***-**-6789 |
MaskingStrategy.Redacted |
<redacted> |
You can roll your own IMaskingService and plug it in through MaskingOptions if you want custom behavior (different patterns, role-based rules, etc.).
Masking is also opt-in per request—leave MaskingContext.Enabled set to false and the library will just write the original values. That’s handy for internal tooling, auditing flows, or when a user has the right to view their own data.
Building locally
dotnet restore
dotnet build
dotnet test
Tip: run ./install-dependencies.sh (or the PowerShell equivalent on Windows) to install consistent tooling like the matching .NET SDK and the pre-commit hooks.
Releasing
Releases are automated through GitHub Actions:
- Open a pull request with conventional commits.
- Create a PR into
main - Once it is merged, a Github Action workflow would publish to NuGet and create downloadable artifacts.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Json.Masker.Abstract (>= 0.4.4)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.IO.RecyclableMemoryStream (>= 3.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.14 | 148 | 10/17/2025 |
| 1.1.11 | 185 | 10/16/2025 |
| 1.1.9 | 195 | 10/16/2025 |
| 1.1.7 | 177 | 10/16/2025 |
| 1.1.5 | 182 | 10/16/2025 |
| 1.1.3 | 189 | 10/16/2025 |
| 1.1.1 | 187 | 10/13/2025 |
| 1.0.7 | 185 | 10/13/2025 |
| 1.0.5 | 194 | 10/12/2025 |
| 1.0.3 | 187 | 10/12/2025 |
| 1.0.0 | 189 | 10/12/2025 |
| 0.5.5 | 124 | 10/10/2025 |
| 0.5.3 | 120 | 10/10/2025 |
| 0.5.1 | 115 | 10/10/2025 |
| 0.5.0 | 121 | 10/10/2025 |
| 0.4.10 | 158 | 10/10/2025 |
| 0.4.6 | 172 | 10/10/2025 |
| 0.4.4 | 167 | 10/10/2025 |
| 0.4.2 | 163 | 10/10/2025 |
| 0.4.0 | 193 | 10/10/2025 |
See the changelog at https://github.com/myarichuk/Json.Masker/blob/main/CHANGELOG.md