JsonSubTypes 2.2.0
dotnet add package JsonSubTypes --version 2.2.0
NuGet\Install-Package JsonSubTypes -Version 2.2.0
<PackageReference Include="JsonSubTypes" Version="2.2.0" />
<PackageVersion Include="JsonSubTypes" Version="2.2.0" />
<PackageReference Include="JsonSubTypes" />
paket add JsonSubTypes --version 2.2.0
#r "nuget: JsonSubTypes, 2.2.0"
#:package JsonSubTypes@2.2.0
#addin nuget:?package=JsonSubTypes&version=2.2.0
#tool nuget:?package=JsonSubTypes&version=2.2.0
JsonSubTypes
JsonSubTypes is a discriminated Json sub-type Converter implementation for .NET
Which package? State and choices
JsonSubTypes exists in two packages that share the same API and registration model (attributes and JsonSubtypesConverterBuilder):
JsonSubTypes— forNewtonsoft.Json, the original and stable package.JsonSubTypes.Text.Json(.NET 8+) — forSystem.Text.Json. Experimental: the API is complete and the code fully tested, but the stable1.0.0release is still pending.
The examples below use the Newtonsoft.Json package; the API is the same for System.Text.Json, so read them either way. If you are targeting System.Text.Json, then after these examples jump to the System.Text.Json variant section, which explains the engines available there (Build() converter, BuildResolver(), AOT generator) and their differences and limitations.
Security: unless a subtype mapping is explicitly declared, the converter resolves subtypes by name from the JSON discriminator (only types assignable from the base are considered). See the security section before exposing a name-based hierarchy to untrusted JSON.
DeserializeObject with custom type property name
[JsonConverter(typeof(JsonSubtypes), "Kind")]
public interface IAnimal
{
string Kind { get; }
}
public class Dog : IAnimal
{
public string Kind { get; } = "Dog";
public string Breed { get; set; }
}
public class Cat : IAnimal {
public string Kind { get; } = "Cat";
public bool Declawed { get; set;}
}
The second parameter of the JsonConverter attribute is the JSON property name that will be use to retreive the type information from JSON.
var animal = JsonConvert.DeserializeObject<IAnimal>("{\"Kind\":\"Dog\",\"Breed\":\"Jack Russell Terrier\"}");
Assert.AreEqual("Jack Russell Terrier", (animal as Dog)?.Breed);
N.B.: This only works for types in the same assembly as the base type/interface and either in the same namespace or with a fully qualified type name.
DeserializeObject with custom type mapping
[JsonConverter(typeof(JsonSubtypes), "Sound")]
[JsonSubtypes.KnownSubType(typeof(Dog), "Bark")]
[JsonSubtypes.KnownSubType(typeof(Cat), "Meow")]
public class Animal
{
public virtual string Sound { get; }
public string Color { get; set; }
}
public class Dog : Animal
{
public override string Sound { get; } = "Bark";
public string Breed { get; set; }
}
public class Cat : Animal
{
public override string Sound { get; } = "Meow";
public bool Declawed { get; set; }
}
var animal = JsonConvert.DeserializeObject<IAnimal>("{\"Sound\":\"Bark\",\"Breed\":\"Jack Russell Terrier\"}");
Assert.AreEqual("Jack Russell Terrier", (animal as Dog)?.Breed);
N.B.: Also works with other kind of value than string, i.e.: enums, int, ...
SerializeObject and DeserializeObject with custom type property only present in JSON
This mode of operation only works when JsonSubTypes is explicitely registered in JSON.NET's serializer settings, and not through the [JsonConverter] attribute.
public abstract class Animal
{
public int Age { get; set; }
}
public class Dog : Animal
{
public bool CanBark { get; set; } = true;
}
public class Cat : Animal
{
public int Lives { get; set; } = 7;
}
public enum AnimalType
{
Dog = 1,
Cat = 2
}
Registration:
var settings = new JsonSerializerSettings();
settings.Converters.Add(JsonSubtypesConverterBuilder
.Of(typeof(Animal), "Type") // type property is only defined here
.RegisterSubtype(typeof(Cat), AnimalType.Cat)
.RegisterSubtype(typeof(Dog), AnimalType.Dog)
.SerializeDiscriminatorProperty() // ask to serialize the type property
.Build());
or using syntax with generics:
var settings = new JsonSerializerSettings();
settings.Converters.Add(JsonSubtypesConverterBuilder
.Of<Animal>("Type") // type property is only defined here
.RegisterSubtype<Cat>(AnimalType.Cat)
.RegisterSubtype<Dog>(AnimalType.Dog)
.SerializeDiscriminatorProperty() // ask to serialize the type property
.Build());
De-/Serialization:
var cat = new Cat { Age = 11, Lives = 6 }
var json = JsonConvert.SerializeObject(cat, settings);
Assert.Equal("{\"Lives\":6,\"Age\":11,\"Type\":2}", json);
var result = JsonConvert.DeserializeObject<Animal>(json, settings);
Assert.Equal(typeof(Cat), result.GetType());
Assert.Equal(11, result.Age);
Assert.Equal(6, (result as Cat)?.Lives);
DeserializeObject mapping by property presence
[JsonConverter(typeof(JsonSubtypes))]
[JsonSubtypes.KnownSubTypeWithProperty(typeof(Employee), "JobTitle")]
[JsonSubtypes.KnownSubTypeWithProperty(typeof(Artist), "Skill")]
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Employee : Person
{
public string Department { get; set; }
public string JobTitle { get; set; }
}
public class Artist : Person
{
public string Skill { get; set; }
}
or using syntax with generics:
string json = "[{\"Department\":\"Department1\",\"JobTitle\":\"JobTitle1\",\"FirstName\":\"FirstName1\",\"LastName\":\"LastName1\"}," +
"{\"Department\":\"Department1\",\"JobTitle\":\"JobTitle1\",\"FirstName\":\"FirstName1\",\"LastName\":\"LastName1\"}," +
"{\"Skill\":\"Painter\",\"FirstName\":\"FirstName1\",\"LastName\":\"LastName1\"}]";
var persons = JsonConvert.DeserializeObject<IReadOnlyCollection<Person>>(json);
Assert.AreEqual("Painter", (persons.Last() as Artist)?.Skill);
Registration:
settings.Converters.Add(JsonSubtypesWithPropertyConverterBuilder
.Of(typeof(Person))
.RegisterSubtypeWithProperty(typeof(Employee), "JobTitle")
.RegisterSubtypeWithProperty(typeof(Artist), "Skill")
.Build());
or
settings.Converters.Add(JsonSubtypesWithPropertyConverterBuilder
.Of<Person>()
.RegisterSubtypeWithProperty<Employee>("JobTitle")
.RegisterSubtypeWithProperty<Artist>("Skill")
.Build());
A default class other than the base type can be defined
[JsonConverter(typeof(JsonSubtypes))]
[JsonSubtypes.KnownSubType(typeof(ConstantExpression), "Constant")]
[JsonSubtypes.FallBackSubType(typeof(UnknownExpression))]
public interface IExpression
{
string Type { get; }
}
Or with code configuration:
settings.Converters.Add(JsonSubtypesConverterBuilder
.Of(typeof(IExpression), "Type")
.SetFallbackSubtype(typeof(UnknownExpression))
.RegisterSubtype(typeof(ConstantExpression), "Constant")
.Build());
settings.Converters.Add(JsonSubtypesWithPropertyConverterBuilder
.Of(typeof(IExpression))
.SetFallbackSubtype(typeof(UnknownExpression))
.RegisterSubtype(typeof(ConstantExpression), "Value")
.Build());
System.Text.Json variant
Status: experimental. The
JsonSubTypes.Text.Jsonpackage is a release candidate (1.0.0-rc.x) and not yet part of the project's stable offering. The code is fully tested (133 unit tests) and the API is complete, but the stable1.0.0release will follow once the package has been exercised in more real-world projects.
A variant of the library for System.Text.Json (.NET 8+) is available in the JsonSubTypes.Text.Json namespace and package. It supports the same attribute-driven and builder-driven API, adapted to System.Text.Json idioms.
Attribute based discriminator
using JsonSubTypes.Text.Json;
[JsonSubTypeConverter(typeof(JsonSubtypes<Animal>), "Sound")]
[KnownSubType(typeof(Dog), "Bark")]
[KnownSubType(typeof(Cat), "Meow")]
public class Animal
{
public virtual string Sound { get; }
public string Color { get; set; }
}
public class Dog : Animal
{
public override string Sound { get; } = "Bark";
public string Breed { get; set; }
}
public class Cat : Animal
{
public override string Sound { get; } = "Meow";
public bool Declawed { get; set; }
}
var animal = JsonSerializer.Deserialize<Animal>("{\"Sound\":\"Bark\",\"Breed\":\"Jack Russell Terrier\"}");
Assert.AreEqual("Jack Russell Terrier", (animal as Dog)?.Breed);
Like the native [JsonDerivedType] polymorphism, the attribute-based converter handles both directions: serializing through the base type writes the discriminator, and deserialization reads it back, so round-trips work out of the box:
var json = JsonSerializer.Serialize<Animal>(new Dog { Breed = "Jack Russell Terrier" });
// {"Sound":"Bark","Breed":"Jack Russell Terrier"}
var back = JsonSerializer.Deserialize<Animal>(json);
Assert.IsInstanceOf<Dog>(back);
When the runtime type is not declared in the [KnownSubType] mappings (e.g. a multi-level hierarchy where the leaf is registered on an intermediate base), serialization falls back to the plain runtime-type contract without a discriminator.
Builder based dynamic registration
var options = new JsonSerializerOptions();
options.Converters.Add(JsonSubtypesConverterBuilder
.Of(typeof(Animal), "type")
.RegisterSubtype(typeof(Cat), AnimalType.Cat)
.RegisterSubtype(typeof(Dog), AnimalType.Dog)
.Build());
var result = JsonSerializer.Deserialize<Animal>("{\"catLives\":6,\"type\":2,\"age\":11}", options);
Assert.AreEqual(typeof(Cat), result.GetType());
Native resolver via BuildResolver()
JsonSubtypesConverterBuilder also exposes the native System.Text.Json polymorphic contract model (JsonPolymorphismOptions) as an alternative to Build(). Assign the result to JsonSerializerOptions.TypeInfoResolver instead of Converters:
var options = new JsonSerializerOptions
{
TypeInfoResolver = JsonSubtypesConverterBuilder
.Of(typeof(Animal), "type")
.RegisterSubtype(typeof(Cat), AnimalType.Cat)
.RegisterSubtype(typeof(Dog), AnimalType.Dog)
.SerializeDiscriminatorProperty()
.BuildResolver()
};
The resolver delegates all serialization work to System.Text.Json, so it only supports a subset of the converter configuration and throws at build time otherwise: string or int discriminator values, a single level of hierarchy per base type, and the discriminator always written first. The following native behaviors are exposed as opt-in builder methods:
FallBackToNearestAncestor(): an unregistered derived type is serialized as its nearest registered ancestor instead of throwing.IgnoreUnrecognizedTypeDiscriminators(): an unknown type discriminator falls back to the base type instead of throwing.SetFallbackSubtype(baseType)enables the same behavior.- When no subtype is registered explicitly,
[KnownSubType]and[FallBackSubType]attributes on the base type are honored.
For several base type hierarchies, combine builders with JsonSubtypesConverterBuilder.BuildResolvers(...). Combining resolvers through JsonSerializerOptions.TypeInfoResolverChain does not work, because each resolver answers for every type and only the first one would be applied.
Serializing the discriminator
The attribute-based converter writes the discriminator by default. For the builder, writing the discriminator is opt-in, like the Newtonsoft version:
options.Converters.Add(JsonSubtypesConverterBuilder
.Of(typeof(Animal), "type")
.SerializeDiscriminatorProperty() // discriminator first (default)
// or .SerializeDiscriminatorProperty(false) // discriminator last
.RegisterSubtype(typeof(Cat), AnimalType.Cat)
.RegisterSubtype(typeof(Dog), AnimalType.Dog)
.Build());
var json = JsonSerializer.Serialize<Animal>(new Cat { Age = 11, Lives = 6 }, options);
// {"type":2,"catLives":6,"age":11}
As with the native [JsonDerivedType] polymorphism, serialization must go through the base type (or a base-typed property/collection) for the converter and the discriminator to apply. Serializing a value with a concrete subtype as its static type bypasses the converter, and serializing an unregistered type throws when SerializeDiscriminatorProperty() is used.
Mapping by property presence
[JsonSubTypeConverter(typeof(JsonSubtypes<Person>))]
[KnownSubTypeWithProperty(typeof(Employee), "JobTitle")]
[KnownSubTypeWithProperty(typeof(Artist), "Skill")]
public class Person { }
Fallback subtype
[JsonSubTypeConverter(typeof(JsonSubtypes<IExpression>), "Type")]
[KnownSubType(typeof(ConstantExpression), "Constant")]
[FallBackSubType(typeof(UnknownExpression))]
public interface IExpression { }
Differences with the Newtonsoft.Json version
- The attribute-based converter writes the discriminator by default (like the native
[JsonDerivedType]polymorphism), whereas the Newtonsoft version never writes it from attributes (CanWrite = false). With the builder, writing is opt-in viaSerializeDiscriminatorProperty(). - With
System.Text.Json, the converter is only applied when the static type is the polymorphic base type (or a base-typed property/collection), matching the native[JsonDerivedType]behavior. The Newtonsoft version also applies converters when serializing a value whose static type is a concrete subtype. - A property declared with a base class or interface type is serialized using the declared type's contract: subtype members are omitted unless a converter that claims the declared type is applied (attribute on the type, or builder registered in
JsonSerializerOptions). The Newtonsoft version serialized the runtime type by default. - Property order differs:
System.Text.Jsonemits properties most-derived-first, while the Newtonsoft version honored[JsonProperty(Order = N)]. There is noOrdersupport inSystem.Text.Json. - Deeply nested graphs need
MaxDepthabout one level higher than with the Newtonsoft/plain serialization: the discriminator write path round-trips through aJsonDocument, which consumes one depth level. (A 64-level chain requiresMaxDepth = 66instead of 65.) - Name-based type resolution stays scoped to the base type's assembly by default. Cross-assembly subtypes require an explicit opt-in:
JsonSubTypesTypeResolution.AddAssembly(...), a capability the Newtonsoft version does not have. JsonNamingPolicyandPropertyNameCaseInsensitiveare respected when matching the discriminator property, andJsonStringEnumConverteris respected when mapping discriminator values. Note thatJsonStringEnumConverter(.NET 8) does not honor[EnumMember(Value = ...)]— use enum names or[JsonStringEnumMemberName](.NET 9+).- Dotted or nested discriminator property paths (e.g.
"nested.property") are supported. - Fallback paths: serializing the base type itself (rather than a subtype) and deserializing an unknown discriminator back to the base use a reflection-based writer/reader, because the base type's contract is owned by the converter (
System.Text.Jsonexposes no property metadata for converter-owned types).[JsonPropertyName],[JsonIgnore](includingJsonIgnoreCondition), the naming policy andDefaultIgnoreConditionare honored; per-property[JsonConverter],[JsonInclude]fields,requiredmembers and parameterized constructors are not supported on these two paths. - Performance: writing an object with a discriminator serializes it once, then re-parses the JSON (
JsonDocument) to inject the discriminator property, so payloads spend roughly 2-3x their size in temporary memory on the write path. This is the cost of the converter architecture and of theMaxDepth + 1note above. - Security: see the security section at the bottom of this section. It applies to both packages; the only difference is the set of assemblies searched for a name-based hit.
- The property-presence builder (
JsonSubtypesWithPropertyConverterBuilder) registers subtypes by property name, so two subtypes cannot share the same property name through the builder (use[KnownSubTypeWithProperty]attributes for that case).
Security
When a subtype is resolved by name — which happens for both packages only when no subtype mapping is declared at all (no [KnownSubType] attribute, no RegisterSubtype builder call) — the converter turns the JSON discriminator string into a type name and instantiates the matching type. Declaring a mapping at all switches the converter to that mapping, even when no entry matches; the name-based path is never used then.
Only types assignable from the polymorphic base type can be resolved, but any such type present in the base type's assembly (for Newtonsoft.Json) or in that assembly plus any assembly registered via JsonSubTypesTypeResolution (for System.Text.Json) can be instantiated with attacker-controlled JSON. Do not expose a name-based hierarchy to untrusted JSON without validating the payload upstream; prefer explicit [KnownSubType] or builder mappings whenever the discriminator can come from outside your own code.
Which engine should I use?
JsonSubTypes.Text.Json ships three engines that share the same configuration layer (the attributes and JsonSubtypesConverterBuilder), and a parity test battery keeps them aligned:
| Feature / Capability | Native STJ ([JsonDerivedType]) |
Resolver (BuildResolver()) |
Converter (Build()) |
Generator (JsonSubTypes.Text.Json.Aot) |
|---|---|---|---|---|
| Type discriminator mapping (string/int) | ✅ | ✅ | ✅ | ✅ |
Enum / null discriminator values |
❌ | ❌ | ✅ | ✅ |
| Custom discriminator property name | ✅ | ✅ | ✅ | ✅ |
Property presence matching (KnownSubTypeWithProperty) |
❌ | ❌ | ✅ | ✅ |
Fallback subtype (FallBackSubType) |
❌ | base only | ✅ | ✅ |
| Discriminator written last | ❌ | ❌ | ✅ | ✅ |
| Naming policy / case-insensitive on the discriminator name | ❌ | ⚠️ | ✅ | ✅ |
Dotted / nested discriminator path ("nested.type") |
❌ | ❌ | ✅ | ✅ |
| Nested (multi-level) hierarchies | ⚠️ | ❌ | ✅ | ✅ |
| Dynamic subtype registration at runtime | ❌ | ❌ | ✅ | ✅ (runtime map) |
| Custom type-name resolution hook | ❌ | ❌ | ✅ (built-in) | ✅ (hook) |
| Cross-assembly / plugin types outside the compilation | ❌ | ❌ | ✅ | ⚠️ (must be in the source-gen context) |
| Native AOT / Trimming support | ✅ | ❌ | ❌ | ✅ |
The three engines in one line:
- Converter (
Build()) — the full-featured runtime engine and the right default for non-AOT applications. - Resolver (
BuildResolver()) — the thin native bridge: simplest and fastest, but limited to the subset the native contract model can express. - Generator (
JsonSubTypes.Text.Json.Aot) — a Roslyn source generator emitting compiled converters: the Native AOT answer, with routing compiled instead of reflected.
The decisive difference is not speed, it is when the hierarchy is known:
Converter (Build()) |
Generator (JsonSubTypes.Text.Json.Aot) |
|
|---|---|---|
| Subtypes known at compile time (attributes on your own types) | ✅ | ✅ |
| Subtypes known only at runtime (plugins, loaded assemblies, config) | ✅ | ✅ (via RegisterDynamicSubtype / resolver hooks) |
| Subtypes in third-party assemblies you cannot annotate | ✅ (builder, no attribute needed) | ❌ (generator only sees the source-gen context) |
The generator reads its registrations from [JsonSubTypesAotConverter]/[KnownSubType]-style attributes at compile time (JsonSubTypesGenerator.cs). It can only route types visible to the compilation it runs in. The converter's Build() accepts a runtime registration through the builder, so it is the only engine that can handle hierarchies whose subtypes are discovered at runtime — plugins, assemblies loaded dynamically, or types you do not own. The generator is the better fit when the hierarchy is fixed and known at build time, and the only engine compatible with trimming/Native AOT.
Converter known scope & fallback path
To preserve full compatibility with advanced features while delegating object serialization to System.Text.Json, the converter isolates base-type serialization to a narrow path (when serializing the base type directly or reading an unregistered fallback type):
- Subtypes (most cases): Full delegation to
System.Text.Json. STJ attributes ([JsonIgnore],[JsonInclude], property[JsonConverter],[JsonConstructor],recordtypes, naming policies) are fully supported natively. - Base-as-leaf & Fallback path: lightweight direct property mapping honoring
[JsonIgnore],[JsonPropertyName], the naming policy andPropertyNameCaseInsensitive. Per-property[JsonConverter],[JsonInclude]fields,requiredmembers and parameterized constructors are not re-implemented on this path. - Parameterless constructor required for the base fallback type. Subtypes resolved via the discriminator support all STJ constructor features (primary constructors,
recordtypes).
Performance (measured)
Benchmarked with BenchmarkDotNet (JsonSubTypes.Benchmarks, .NET 10); the methodology, machine and full result tables are in PERFORMANCE.md. In short:
- Resolver (
BuildResolver()) is the fastest: it delegates toSystem.Text.Jsonnative polymorphism, with noJsonDocumentround-trip and no reflection per call. - Generator (
JsonSubTypes.Text.Json.Aot) beats the runtime converter on deserialization and allocates far less (compiled routing instead of per-call converter scans). Its Native AOT steady state is comparable to (slightly slower than) JIT; its real advantage is trimming compatibility and startup time. - Converter (
Build()) is the slowest of the three: it keeps theJsonDocumentround-trip and adds runtime type resolution. It is the only engine for hierarchies whose subtypes are only known at runtime. - Newtonsoft.Json (
JsonSubTypes) is slower and allocates several times more than the STJ converter on the same scenarios.
Reproduce the measurements yourself with dotnet run -c Release --project JsonSubTypes.Benchmarks -- --filter "*" (a native compiler is needed for the Native AOT job; see PERFORMANCE.md).
Decision matrix
| Use case | Recommended |
|---|---|
| Native AOT / trimming, hierarchy known at compile time | JsonSubTypes.Text.Json.Aot generator |
| Non-AOT, full feature set with minimal setup | Converter (Build()) |
| Non-AOT, string/int discriminators only, fastest and simplest | Resolver (BuildResolver()) |
| Discriminator by property presence (no discriminator field in the JSON) | Converter or Generator |
| Open hierarchies / subtypes registered at runtime | Converter, or Generator (RegisterDynamicSubtype) |
Non string/int discriminator values (enums, null) |
Converter or Generator |
Nested or dotted discriminator paths (e.g. "nested.property") |
Converter or Generator |
| Resolution by arbitrary .NET type name / cross-assembly plugins | Converter (built-in), or Generator (CustomTypeNameResolver hook) |
| Migrating an existing JsonSubTypes/Newtonsoft code base | Converter (same API) |
Native AOT
The resolver and the converter rely on reflection and are therefore not compatible with trimming or Native AOT. The polymorphic metadata that the resolver configures must be declared at compile time for AOT: System.Text.Json freezes it at build time, and a source-generated JsonTypeInfo is read-only at runtime. Assigning PolymorphismOptions to a source-generated JsonTypeInfo throws InvalidOperationException on both .NET 8 and .NET 10.
For Native AOT, the JsonSubTypes.Text.Json.Aot generator compiles the routing into the converter (verified to run as a native binary with dotnet publish -r linux-x64 -p:PublishAot=true). The generator is referenced as an analyzer and reads its attributes ([JsonSubTypesAotConverter], [KnownSubType], …) from the JsonSubTypes.Text.Json package, so reference both JsonSubTypes.Text.Json.Aot and JsonSubTypes.Text.Json:
dotnet add package JsonSubTypes.Text.Json.Aot
dotnet add package JsonSubTypes.Text.Json
Alternatively, declare the hierarchy with [JsonDerivedType] on the base type and use a plain source-generated context:
[JsonPolymorphic(TypeDiscriminatorPropertyName = "$type")]
[JsonDerivedType(typeof(Circle), "circle")]
[JsonDerivedType(typeof(Square), "square")]
public class Shape { }
[JsonSerializable(typeof(Shape))]
[JsonSerializable(typeof(Circle))]
[JsonSerializable(typeof(Square))]
public partial class ShapeJsonContext : JsonSerializerContext { }
var options = new JsonSerializerOptions { TypeInfoResolver = ShapeJsonContext.Default };
var json = JsonSerializer.Serialize<Shape>(new Circle { Radius = 2 }, options);
// {"$type":"circle","Radius":2}
💖 Support this project
If this project helped you save money or time or simply makes your life also easier, you can give me a cup of coffee =)
License
All projects · Source on GitHub · NuGet · CHANGELOG · MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
| .NET Core | netcoreapp1.0 was computed. netcoreapp1.1 was computed. netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard1.3 is compatible. netstandard1.4 was computed. netstandard1.5 was computed. netstandard1.6 was computed. netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net35 is compatible. net40 is compatible. net403 was computed. net45 is compatible. net451 was computed. net452 was computed. net46 is compatible. net461 was computed. net462 was computed. net463 was computed. net47 is compatible. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen30 was computed. tizen40 was computed. tizen60 was computed. |
| Universal Windows Platform | uap was computed. uap10.0 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 3.5
- Newtonsoft.Json (>= 13.0.4)
-
.NETFramework 4.0
- Newtonsoft.Json (>= 13.0.4)
-
.NETFramework 4.5
- Newtonsoft.Json (>= 13.0.4)
-
.NETFramework 4.6
- Newtonsoft.Json (>= 13.0.4)
-
.NETFramework 4.7
- Newtonsoft.Json (>= 13.0.4)
-
.NETStandard 1.3
- NETStandard.Library (>= 1.6.1)
- Newtonsoft.Json (>= 13.0.4)
- System.Net.Http (>= 4.3.4)
- System.Text.RegularExpressions (>= 4.3.1)
-
.NETStandard 2.0
- Newtonsoft.Json (>= 13.0.4)
NuGet packages (875)
Showing the top 5 NuGet packages that depend on JsonSubTypes:
| Package | Downloads |
|---|---|
|
Okta.Sdk
Official .NET SDK for the Okta API |
|
|
Xero.NetStandard.OAuth2
This is a .NETStandard SDK library, used to communicate with the Xero API using OAuth2.0. See https://github.com/XeroAPI/Xero-NetStandard for more information |
|
|
InfluxDB.Client
The reference client that allows query, write and management (bucket, organization, users) for the InfluxDB 2.x. |
|
|
sib_api_v3_sdk
Official SendinBlue provided RESTFul API V3 C# Library |
|
|
Finbourne.EdpLusidSdk
LUSID SDK for EDP |
GitHub repositories (25)
Showing the top 20 popular GitHub repositories that depend on JsonSubTypes:
| Repository | Stars |
|---|---|
|
BililiveRecorder/BililiveRecorder
录播姬 | mikufans 生放送录制
|
|
|
Azure-Samples/cognitive-services-speech-sdk
Sample code for the Microsoft Cognitive Services Speech SDK
|
|
|
antonpup/Aurora
Unified lighting effects across multiple brands and various games.
|
|
|
jlucansky/Quartzmin
Quartzmin is powerful, easy to use web management tool for Quartz.NET
|
|
|
api-bricks/api-bricks-sdk
SDKs for CoinAPI & FinFeedAPI
|
|
|
takuya-takeuchi/DlibDotNet
Dlib .NET wrapper written in C++ and C# for Windows, MacOS, Linux and iOS
|
|
|
blish-hud/Blish-HUD
A Guild Wars 2 overlay with extreme extensibility through compiled modules.
|
|
|
IoTSharp/SilkierQuartz
SilkierQuartz can host jobs using HostService and Provide a web management tools for Quartz !
|
|
|
influxdata/influxdb-client-csharp
InfluxDB 2.x C# Client
|
|
|
microsoft/verisol
A formal verifier and analysis tool for Solidity Smart Contracts
|
|
|
alipay/alipay-sdk-net-all
支付宝开放平台 Alipay SDK for .NET
|
|
|
notion-dotnet/notion-sdk-net
A Notion SDK for .Net
|
|
|
Anapher/Strive
Open source video conferencing platform
|
|
|
blockchain/lib-exchange-client
|
|
|
kameleo-io/kameleo
Anti-detect browser for web scraping and automation. Engine-level fingerprint masking for Chromium and Firefox. Self-hosted, Docker-ready. Integrates with Selenium, Playwright, and Puppeteer via SDKs in Python, JavaScript, and C#.
|
|
|
christianhelle/apiclientcodegen
A collection of Visual Studio code generators for Swagger / OpenAPI specification files
|
|
|
LexPredict/lexpredict-contraxsuite
LexPredict ContraxSuite
|
|
|
okta/okta-sdk-dotnet
A .NET SDK for interacting with the Okta management API, enabling server-side code to manage Okta users, groups, applications, and more.
|
|
|
bybit-exchange/api-connectors
Libraries for connecting to the Bybit API.
|
|
|
James231/Start-Menu-Manager
App to add websites/software/files/folders/scripts to the Windows 10 Start Menu and Taskbar, and priority shortcuts to Windows 10 Search.
|
| Version | Downloads | Last Updated |
|---|---|---|
| 2.2.0 | 145 | 10/7/2026 |
| 2.1.0 | 398,249 | 8/11/2026 |
| 2.0.1 | 66,425,782 | 10/18/2022 |
| 2.0.0 | 57,734 | 10/18/2022 |
| 1.9.0 | 12,231,180 | 5/9/2022 |
| 1.8.0 | 33,670,097 | 9/23/2020 |
| 1.7.0 | 4,536,103 | 3/28/2020 |
| 1.6.0 | 5,727,694 | 6/24/2019 |
| 1.5.2 | 10,705,804 | 1/19/2019 |
| 1.5.1 | 798,816 | 10/15/2018 |
| 1.5.0 | 108,316 | 8/27/2018 |
| 1.4.0 | 302,566 | 4/17/2018 |
| 1.3.1 | 11,895 | 4/12/2018 |
| 1.3.0 | 93,466 | 1/28/2018 |
| 1.2.0 | 14,441,762 | 11/22/2017 |
| 1.1.3 | 76,046 | 11/15/2017 |
| 1.1.2 | 8,506 | 10/20/2017 |
| 1.1.1 | 7,885 | 9/21/2017 |
| 1.1.0 | 12,899 | 9/19/2017 |
| 1.0.0 | 33,207 | 7/23/2017 |