JsonApiKit.AspNetCore
1.4.0
dotnet add package JsonApiKit.AspNetCore --version 1.4.0
NuGet\Install-Package JsonApiKit.AspNetCore -Version 1.4.0
<PackageReference Include="JsonApiKit.AspNetCore" Version="1.4.0" />
<PackageVersion Include="JsonApiKit.AspNetCore" Version="1.4.0" />
<PackageReference Include="JsonApiKit.AspNetCore" />
paket add JsonApiKit.AspNetCore --version 1.4.0
#r "nuget: JsonApiKit.AspNetCore, 1.4.0"
#:package JsonApiKit.AspNetCore@1.4.0
#addin nuget:?package=JsonApiKit.AspNetCore&version=1.4.0
#tool nuget:?package=JsonApiKit.AspNetCore&version=1.4.0
JsonApiKit
Lightweight JSON:API library for .NET — drop-in resource shapes, pagination, error handling, and query parsing without owning your app architecture.
JsonApiKit gives you the building blocks to produce JSON:API-compliant (or relaxed) responses from any .NET API. It does not take over your routing, controllers, or data access — you stay in control while getting consistent, well-structured output.
Table of Contents
- Packages
- Installation
- Quick Start
- Core Concepts
- Configuration
- Include Depth Tracking
- Sparse Fieldsets
- ASP.NET Core Integration
- EF Core Integration
- Dapper Integration
- Source Generators
- JSON Output Examples
- Sample Application
- License
Packages
| Package | Description | Target |
|---|---|---|
| JsonApiKit | Core types — documents, resources, pagination, errors, serialization. Zero ASP.NET dependency. | netstandard2.1, net8.0, net9.0, net10.0 |
| JsonApiKit.AspNetCore | ASP.NET Core integration — result extensions, exception handling, validation filters, DI registration. | net8.0, net9.0, net10.0 |
| JsonApiKit.EntityFrameworkCore | EF Core integration — query pipeline, cursor/offset pagination, paged responses. | net8.0, net9.0, net10.0 |
| JsonApiKit.Dapper | Dapper integration — SQL query pipeline, cursor/offset pagination, paged responses. | net8.0, net9.0, net10.0 |
| JsonApiKit.SourceGenerators | Roslyn source generators — reduce resource boilerplate with attributes. | netstandard2.0 |
Installation
# Core (required)
dotnet add package JsonApiKit
# ASP.NET Core integration
dotnet add package JsonApiKit.AspNetCore
# EF Core query pipeline
dotnet add package JsonApiKit.EntityFrameworkCore
# Dapper query pipeline
dotnet add package JsonApiKit.Dapper
# Source generators (optional)
dotnet add package JsonApiKit.SourceGenerators
Quick Start
using JsonApiKit.AspNetCore.DependencyInjection;
using JsonApiKit.AspNetCore.Results;
using JsonApiKit.Configuration;
using JsonApiKit.Includes;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddJsonApiKit(options =>
{
options.Mode = JsonApiMode.Relaxed;
options.DefaultPageSize = 10;
options.MaxPageSize = 50;
options.DefaultPaginationType = PaginationType.Cursor;
options.IncludeExceptionDetails = builder.Environment.IsDevelopment();
});
var app = builder.Build();
app.UseExceptionHandler(o => { });
app.MapGet("/api/v1/books/{id:int}", async (int id, MyDbContext db, string? include) =>
{
var includeCtx = IncludeParser.Parse(include);
var book = await db.Books.FindAsync(id);
if (book is null)
return "Book not found".ToJsonApiError("NOT_FOUND", 404);
return new BookResource(book, includeCtx).ToJsonApiResult("BOOK_FETCHED");
});
app.Run();
Core Concepts
Documents
All responses are wrapped in a document type:
// Success response
JsonApiDocument<TData>
{
ResponseCode, // application-level code, e.g. "BOOKS_FETCHED"
ResponseMessage, // human-readable message
HttpCode, // HTTP status code
Data, // the payload
Errors, // optional error list
Meta, // optional metadata dictionary
Links, // optional links
Included // optional sideloaded resources
}
// Error response
JsonApiErrorDocument
{
ResponseCode,
ResponseMessage,
HttpCode,
Errors, // required error list
Meta
}
Resources
Implement IJsonApiResource to define a resource shape:
public class BookResource : IJsonApiResource
{
public string Id { get; set; } = "";
public string Type => "book";
public BookAttributes Attributes { get; set; } = null!;
public BookRelationships? Relationships { get; set; }
public BookResource(Book book, IncludeContext ctx)
{
Id = book.Id.ToString();
Attributes = new BookAttributes(book.Title, book.Slug);
Relationships = ctx.ShouldInclude("author") && book.Author is not null
? new BookRelationships(new AuthorResource(book.Author, ctx.Descend("author")))
: null;
}
}
public record BookAttributes(string Title, string Slug);
public record BookRelationships(AuthorResource? Author);
Typed variants are also available:
IJsonApiResource<TAttributes>— resource with typed attributesIJsonApiResource<TAttributes, TRelationships>— resource with typed attributes and relationships
Relationships
For strict-mode relationship serialization:
// To-one: serializes as { "data": { "id": "1", "type": "author" } }
Relationship<AuthorResource>
// To-many: serializes as { "data": [{ "id": "1", "type": "book" }, ...] }
RelationshipCollection<BookResource>
// Resource identifier
ResourceIdentifier(string Id, string Type)
// Strict relationship records
RelationshipToOne(ResourceIdentifier? Data)
RelationshipToMany(IReadOnlyList<ResourceIdentifier>? Data)
The IncludedCollector deduplicates resources by (Type, Id) for the top-level included array.
Errors
public record JsonApiError
{
public required string Code { get; init; } // e.g. "VALIDATION_ERROR"
public string? Detail { get; init; } // human-readable detail
public string? Status { get; init; } // HTTP status as string
public JsonApiErrorSource? Source { get; init; } // pointer + parameter
public JsonApiMeta? Meta { get; init; }
}
public record JsonApiErrorSource
{
public string? Pointer { get; init; } // e.g. "/data/attributes/title"
public string? Parameter { get; init; } // e.g. "filter"
}
Pagination
Two pagination strategies with polymorphic metadata:
Offset pagination:
PaginationMeta.Offset(new OffsetPage(
Current: 1, Size: 10, Total: 42, TotalPages: 5,
HasNext: true, HasPrevious: false, From: 1, To: 10
))
Cursor pagination:
PaginationMeta.Cursor(new CursorPage(
Size: 10,
Next: "base64-encoded-cursor",
Previous: null
))
PaginationCursor<TId> provides Base64URL-encoded cursors containing timestamp + ID for stable, keyset-based pagination.
Links and Meta
ResourceLinks(string Self) // per-resource self link
PaginationLinks(string? First, string? Last, // page navigation
string? Prev, string? Next)
JsonApiLinks { Self, Related, Pagination } // document-level links
JsonApiMeta : Dictionary<string, object?> // arbitrary metadata
Configuration
builder.Services.AddJsonApiKit(options =>
{
options.Mode = JsonApiMode.Relaxed; // Relaxed (default) or Strict
options.NamingPolicy = JsonNamingPolicy.CamelCase;
options.DefaultPageSize = 10;
options.MaxPageSize = 100;
options.DefaultPaginationType = PaginationType.Cursor;
options.IncludeLinks = false;
options.BaseUrl = "https://api.example.com";
options.IncludeExceptionDetails = false; // true in dev for stack traces
});
Relaxed vs Strict Mode
Relaxed mode (default) — relationships are serialized as full resource objects inline:
{
"data": {
"id": "1",
"type": "book",
"attributes": { "title": "1984" },
"relationships": {
"author": { "id": "1", "type": "author", "attributes": { "name": "George Orwell" } }
}
}
}
Strict mode — follows the JSON:API specification exactly. Relationships contain only resource linkage; full resources go into a top-level included array:
{
"data": {
"id": "1",
"type": "book",
"attributes": { "title": "1984" },
"relationships": {
"author": { "data": { "id": "1", "type": "author" } }
}
},
"included": [
{ "id": "1", "type": "author", "attributes": { "name": "George Orwell" } }
]
}
Include Depth Tracking
IncludeContext is the key mechanism for controlling which relationships get loaded and how deep the inclusion chain goes. It prevents N+1 issues and circular reference bloat.
// Parse the ?include= query parameter
var ctx = IncludeParser.Parse("author,author.books", maxAllowedDepth: 3);
// Check if a relationship should be included at the current level
ctx.ShouldInclude("author"); // true
// Descend into a relationship (increments depth, updates path)
var authorCtx = ctx.Descend("author");
authorCtx.ShouldInclude("books"); // true (matches "author.books")
// Further nesting respects max depth
var booksCtx = authorCtx.Descend("books");
booksCtx.ShouldInclude("author"); // false (depth limit reached)
Usage in resource constructors:
public BookResource(Book book, IncludeContext ctx)
{
Id = book.Id.ToString();
Attributes = new BookAttributes(book.Title, book.Slug);
if (ctx.ShouldInclude("author") && book.Author is not null)
Relationships = new BookRelationships(
new AuthorResource(book.Author, ctx.Descend("author")));
}
IncludeParser.Parse() is case-insensitive, supports comma-separated dot-notation paths, and clamps to a configurable maximum depth (default 3).
Sparse Fieldsets
SparseFieldsetContext parses the fields[type]=field1,field2 query string pattern:
var fieldsetCtx = SparseFieldsetContext.Parse(httpContext.Request.QueryString.Value);
// Check if a specific field should be included for a type
fieldsetCtx.ShouldIncludeField("book", "title"); // true or false
// Get all requested fields for a type
HashSet<string>? fields = fieldsetCtx.GetFieldsFor("book");
Sparse fieldsets are not enforced at the serialization layer — they are designed to be checked during resource mapping so you have full control over field filtering.
ASP.NET Core Integration
DI Registration
builder.Services.AddJsonApiKit(options =>
{
options.Mode = JsonApiMode.Relaxed;
// ...
});
This registers IOptions<JsonApiOptions>, a configured JsonSerializerOptions singleton, and JsonApiExceptionHandler.
Result Extensions
Convert values directly to JSON:API responses:
// Success
var resource = new BookResource(book, includeCtx);
return resource.ToJsonApiResult("BOOK_FETCHED");
return resource.ToJsonApiResult("BOOK_CREATED", "Book created successfully", 201);
// Error from string
return "Book not found".ToJsonApiError("NOT_FOUND", 404);
return "Unauthorized".ToJsonApiError("UNAUTHORIZED", 401, "You must be logged in");
// Validation errors
return errors.ToJsonApiValidationError(validationDictionary);
Exception Handler
Unhandled exceptions are automatically mapped to JsonApiErrorDocument:
| Exception | HTTP Status | Code |
|---|---|---|
KeyNotFoundException |
404 | NOT_FOUND |
ArgumentException |
400 | BAD_REQUEST |
UnauthorizedAccessException |
401 | UNAUTHORIZED |
NotSupportedException |
405 | METHOD_NOT_ALLOWED |
| Other | 500 | INTERNAL_ERROR |
Stack traces are included when IncludeExceptionDetails = true (recommended for development only).
app.UseExceptionHandler(o => { });
Validation Filter
Add the endpoint filter to validate request bodies:
app.MapPost("/api/v1/books", (CreateBookRequest request) => { ... })
.AddEndpointFilter<JsonApiValidationFilter>();
Validators implement IJsonApiValidator<T> and produce field-level errors with JSON:API source pointers:
{
"responseCode": "VALIDATION_ERROR",
"httpCode": 422,
"errors": [
{
"code": "VALIDATION_ERROR",
"detail": "Title is required",
"status": "422",
"source": { "pointer": "/data/attributes/title" }
}
]
}
EF Core Integration
IQueryableEntity
Implement IQueryableEntity<T> on your entities to define filter, sort, and include logic as static methods:
public class Book : IQueryableEntity<Book>
{
public int Id { get; set; }
public string Title { get; set; } = "";
public int AuthorId { get; set; }
public Author Author { get; set; } = null!;
public DateTime CreatedAt { get; set; }
public static IQueryable<Book> ApplyFilter(IQueryable<Book> query, object? filter)
{
if (filter is string search && !string.IsNullOrWhiteSpace(search))
return query.Where(b => b.Title.Contains(search));
return query;
}
public static IQueryable<Book> ApplySort(IQueryable<Book> query, string? sort) => sort switch
{
"title" => query.OrderBy(b => b.Title).ThenBy(b => b.Id),
"-title" => query.OrderByDescending(b => b.Title).ThenByDescending(b => b.Id),
_ => query.OrderByDescending(b => b.CreatedAt).ThenByDescending(b => b.Id)
};
public static IQueryable<Book> ApplyInclude(
IQueryable<Book> query, object? include, IncludeContext context)
{
if (context.ShouldInclude("author"))
query = query.Include(b => b.Author);
return query;
}
}
Paged Responses
ToPagedResponseAsync chains filter → sort → include → paginate → map in one call:
var includeCtx = IncludeParser.Parse(include);
var request = new ApiRequest<string?, string?, object>
{
Include = include,
Filter = filter,
Sort = sort,
Page = new RequestPage { Size = pageSize, Number = pageNumber }
};
var result = await db.Books
.ToPagedResponseAsync<Book, string?, string?, object, BookResource>(
request,
(entity, ctx) => new BookResource(entity, ctx),
includeCtx);
return result.ToJsonApiResult("BOOKS_FETCHED");
Supports both offset pagination (pageNumber/pageSize) and cursor pagination with PaginationCursor<TId>.
Dapper Integration
IDapperEntity
Implement IDapperEntity<T> on your entities to define filter, sort, and include logic using raw SQL:
using JsonApiKit.Dapper.Includes;
public class Book : IDapperEntity<Book>
{
public int Id { get; set; }
public string Title { get; set; } = "";
public int AuthorId { get; set; }
public Author? Author { get; set; }
public ICollection<Category>? Categories { get; set; }
public DateTime CreatedAt { get; set; }
public static string BaseSql => "SELECT Id, Title, Slug, AuthorId, CreatedAt FROM Books";
static IReadOnlyList<WhereClause> IDapperEntity<Book>.GetGlobalFilters() =>
[new("DeletedAt IS NULL")];
static IReadOnlyList<RelationshipDescriptor> IDapperEntity<Book>.GetRelationships() =>
[
new BelongsTo<Author>("author", nameof(AuthorId),
"SELECT Id, Name FROM Authors WHERE Id IN @Ids"),
new HasManyThrough<Category, (int BooksId, int CategoriesId)>("categories",
"BooksId", "CategoriesId",
"SELECT BooksId, CategoriesId FROM BookCategories WHERE BooksId IN @Ids",
"SELECT Id, Name FROM Categories WHERE Id IN @Ids")
];
public static IReadOnlyList<WhereClause> ApplyFilter(object? filter)
{
if (filter is string search && !string.IsNullOrWhiteSpace(search))
return [new WhereClause("Title LIKE @search",
new Dictionary<string, object?> { ["search"] = $"%{search}%" })];
return [];
}
public static OrderByClause ApplySort(string? sort) => sort switch
{
"title" => new OrderByClause("Title ASC, Id ASC"),
"-title" => new OrderByClause("Title DESC, Id DESC"),
_ => new OrderByClause("CreatedAt DESC, Id DESC")
};
// No ApplyIncludeAsync needed — default implementation uses GetRelationships()
}
Key differences from EF Core's IQueryableEntity<T>:
BaseSqlreplaces theIQueryable<T>starting pointApplyFilterreturnsWhereClauseSQL fragments instead of chaining LINQApplySortreturns anOrderByClauseSQL fragment instead of LINQ OrderByGetRelationships()declares includes declaratively — the engine handles SQL executionApplyIncludeAsyncis optional — override it only for custom include logic
Global Filters
GetGlobalFilters() defines WHERE clauses applied to every query (e.g., soft-delete):
static IReadOnlyList<WhereClause> IDapperEntity<Book>.GetGlobalFilters() =>
[new("deleted_at IS NULL")];
Bypass global filters for admin queries:
await connection.ToPagedResponseAsync<Book, ...>(..., ignoreGlobalFilters: true);
Relationship Descriptors
Declare relationships once — the engine handles SQL execution and entity mapping automatically.
Attribute-based (recommended) — co-locate relationship config with navigation properties and let the source generator emit GetRelationships() at compile time:
using JsonApiKit.Dapper.Includes;
public partial class Book : IDapperEntity<Book>
{
public int AuthorId { get; set; }
[BelongsTo(Sql = "SELECT Id, Name FROM Authors WHERE Id = ANY(@Ids)")]
public Author? Author { get; set; } // FK = "AuthorId" (convention), name = "author" (inferred)
[HasManyThrough(
PivotEntityKey = "BooksId", PivotRelatedKey = "CategoriesId",
PivotSql = "SELECT BooksId, CategoriesId FROM BookCategories WHERE BooksId = ANY(@Ids)",
RelatedSql = "SELECT Id, Name FROM Categories WHERE Id = ANY(@Ids)")]
public ICollection<Category>? Categories { get; set; } // name = "categories" (inferred)
// No GetRelationships() method needed — source generator emits it at build time
}
The generator infers:
- FK for
[BelongsTo]:{PropertyName}Idby convention (override with[BelongsTo("CustomFkName")]) - Name: lowercase property name (override with
Name = "custom") - Related type: from property type (
Author?) or collection element type (ICollection<Category>)
Three attribute types:
| Attribute | Relationship | Required Properties |
|---|---|---|
[BelongsTo] |
FK on this entity → single related | Sql |
[HasMany("FkName")] |
FK on related entity → collection | Sql |
[HasManyThrough] |
Junction table → many-to-many | PivotEntityKey, PivotRelatedKey, PivotSql, RelatedSql |
Compile-time diagnostics are reported for missing required properties or non-partial classes.
Manual approach — for advanced scenarios, you can still implement GetRelationships() directly:
public class Book : IDapperEntity<Book>
{
static IReadOnlyList<RelationshipDescriptor> IDapperEntity<Book>.GetRelationships() =>
[
new BelongsTo<Author>("author", nameof(AuthorId),
"SELECT ... FROM Authors WHERE Id = ANY(@Ids)"),
new HasManyThrough<Category, (int BooksId, int CategoriesId)>("categories",
"BooksId", "CategoriesId",
"SELECT BooksId, CategoriesId FROM BookCategories WHERE BooksId = ANY(@Ids)",
"SELECT ... FROM Categories WHERE Id = ANY(@Ids)")
];
}
Four descriptor records:
- BelongsTo<T> — FK on this entity, loads single related (e.g. Book → Author)
- HasMany<T> — FK on related entity, loads collection (e.g. Author → Books)
- HasManyThrough<T, TPivot> — junction table with typed pivot struct
- HasManyThroughDynamic<T> — junction table without pivot type (uses dynamic queries)
Custom ID converters for non-standard ID types (e.g. Ulid):
IdConverter.SetDefault(id => ((Ulid)id).ToByteArray());
Entities with custom include logic can still override ApplyIncludeAsync directly.
SQL Builder
The WhereClause and OrderByClause types represent SQL fragments:
// WHERE fragment with parameterized values (parameters are auto-remapped to prevent collisions)
new WhereClause("Title LIKE @search", new Dictionary<string, object?> { ["search"] = "%1984%" })
// ORDER BY fragment
new OrderByClause("CreatedAt DESC, Id DESC")
Dapper Paged Responses
ToPagedResponseAsync on DbConnection chains filter → sort → include → paginate → map, mirroring the EF Core pipeline:
var includeCtx = IncludeParser.Parse(include);
var request = new ApiRequest<string?, string?, object>
{
Include = include,
Filter = filter,
Sort = sort,
Page = new RequestPage { Size = pageSize, Number = pageNumber }
};
var result = await connection
.ToPagedResponseAsync<Book, string?, string?, object, BookResource>(
request,
(entity, ctx) => new BookResource(entity, ctx),
includeCtx);
return result.ToJsonApiResult("BOOKS_FETCHED");
Three overloads are available, matching EF Core:
- Basic — no postProcess, no auto-cursor
- With
postProcesscallback — runs before resource mapping - With
ICursorableEntity<TId>— automatic keyset cursor pagination
Source Generators
The JsonApiKit.SourceGenerators package provides two Roslyn incremental generators that reduce boilerplate at compile time with zero reflection and full AOT compatibility.
Resource Generator
Reduce resource boilerplate with the [JsonApiResource] attribute:
[JsonApiResource("book", "/api/v1/books")]
public partial class BookResource
{
public string Id { get; set; }
[JsonApiAttribute]
public string Title { get; set; }
[JsonApiRelationship("author")]
public AuthorResource? Author { get; set; }
}
The generator produces a partial class with the Type property and Links based on the resource type and base path.
Dapper Relationship Generator
Declare Dapper relationship descriptors as attributes on navigation properties — the generator emits GetRelationships() at compile time:
public partial class Book : IDapperEntity<Book>
{
public int AuthorId { get; set; }
[BelongsTo(Sql = "SELECT Id, Name FROM Authors WHERE Id = ANY(@Ids)")]
public Author? Author { get; set; }
[HasMany("AuthorId", Sql = "SELECT Id, Title FROM Books WHERE AuthorId = ANY(@Ids)")]
public ICollection<Book>? Books { get; set; }
[HasManyThrough(
PivotEntityKey = "BooksId", PivotRelatedKey = "CategoriesId",
PivotSql = "SELECT BooksId, CategoriesId FROM BookCategories WHERE BooksId = ANY(@Ids)",
RelatedSql = "SELECT Id, Name FROM Categories WHERE Id = ANY(@Ids)")]
public ICollection<Category>? Categories { get; set; }
}
// Generated at compile time:
// partial class Book {
// static IReadOnlyList<RelationshipDescriptor> IDapperEntity<Book>.GetRelationships() => [ ... ];
// }
The generator reports compile-time diagnostics:
| Code | Description |
|---|---|
| JAPI001 | [BelongsTo] requires Sql property |
| JAPI002 | [HasMany] requires Sql property |
| JAPI003 | [HasManyThrough] requires PivotSql and RelatedSql |
| JAPI004 | [HasManyThrough] requires PivotEntityKey and PivotRelatedKey |
| JAPI006 | Class with relationship attributes must be partial |
All attributes are emitted via RegisterPostInitializationOutput, so consuming projects only need the analyzer reference — no additional package dependency.
JSON Output Examples
Success (relaxed mode):
{
"responseCode": "BOOKS_FETCHED",
"responseMessage": "Success",
"httpCode": 200,
"data": [
{
"id": "1",
"type": "book",
"attributes": {
"title": "1984",
"slug": "1984"
},
"relationships": {
"author": {
"id": "1",
"type": "author",
"attributes": {
"name": "George Orwell",
"slug": "george-orwell"
}
}
}
}
],
"meta": {
"paginationType": "cursor",
"page": {
"size": 10,
"next": "eyJjcmVhdGVkQXQiOiIyMDI2LTAxLTAxIiwiaWQiOjF9"
}
}
}
Error:
{
"responseCode": "NOT_FOUND",
"responseMessage": "Book not found",
"httpCode": 404,
"errors": [
{
"code": "NOT_FOUND",
"detail": "Book not found",
"status": "404"
}
]
}
Sample Applications
EF Core Sample
A complete working example is included at samples/JsonApiKit.Sample/. It demonstrates:
- SQLite database with
AuthorandBookentities IQueryableEntity<T>implementations with filter, sort, and include- Resource constructors with
IncludeContextdepth tracking ToPagedResponseAsyncquery pipeline- Exception handler and result extensions
cd samples/JsonApiKit.Sample
dotnet run
Dapper Sample
A Dapper equivalent is at samples/JsonApiKit.Dapper.Sample/. It demonstrates:
- SQLite database with raw SQL table creation
IDapperEntity<T>implementations with SQL-based filter, sort, and include- Post-fetch relationship loading via
ApplyIncludeAsync ToPagedResponseAsynconDbConnection
cd samples/JsonApiKit.Dapper.Sample
dotnet run
Both samples expose the same endpoints:
GET /api/v1/books— list books with paginationGET /api/v1/books?include=author— include author relationshipGET /api/v1/books/1— single bookGET /api/v1/authors— list authorsGET /api/v1/error— exception handler demo
License
MIT — Copyright (c) 2026 JsonApiKit Contributors
| 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 is compatible. 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 is compatible. 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. |
-
net10.0
- JsonApiKit (>= 1.4.0)
- Microsoft.AspNetCore.OpenApi (>= 10.0.5)
-
net8.0
- JsonApiKit (>= 1.4.0)
-
net9.0
- JsonApiKit (>= 1.4.0)
- Microsoft.AspNetCore.OpenApi (>= 9.0.14)
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.4.0 | 152 | 4/1/2026 |
| 1.3.13 | 206 | 3/26/2026 |
| 1.3.11 | 102 | 3/26/2026 |
| 1.3.9 | 97 | 3/25/2026 |
| 1.3.8 | 107 | 3/25/2026 |
| 1.3.7 | 109 | 3/25/2026 |
| 1.3.6 | 114 | 3/7/2026 |
| 1.3.5 | 98 | 3/7/2026 |
| 1.3.4 | 104 | 3/7/2026 |
| 1.3.3 | 106 | 3/7/2026 |
| 1.3.2 | 103 | 3/5/2026 |
| 1.3.1 | 103 | 3/5/2026 |
| 1.3.0 | 113 | 3/5/2026 |
| 1.2.2 | 125 | 2/27/2026 |
| 1.2.1 | 104 | 2/26/2026 |
| 1.2.0 | 109 | 2/26/2026 |
| 1.1.0 | 107 | 2/26/2026 |
| 1.0.0 | 110 | 2/23/2026 |