IIIF.Manifest.Serializer.Net.TextGranularity
3.0.17
dotnet add package IIIF.Manifest.Serializer.Net.TextGranularity --version 3.0.17
NuGet\Install-Package IIIF.Manifest.Serializer.Net.TextGranularity -Version 3.0.17
<PackageReference Include="IIIF.Manifest.Serializer.Net.TextGranularity" Version="3.0.17" />
<PackageVersion Include="IIIF.Manifest.Serializer.Net.TextGranularity" Version="3.0.17" />
<PackageReference Include="IIIF.Manifest.Serializer.Net.TextGranularity" />
paket add IIIF.Manifest.Serializer.Net.TextGranularity --version 3.0.17
#r "nuget: IIIF.Manifest.Serializer.Net.TextGranularity, 3.0.17"
#:package IIIF.Manifest.Serializer.Net.TextGranularity@3.0.17
#addin nuget:?package=IIIF.Manifest.Serializer.Net.TextGranularity&version=3.0.17
#tool nuget:?package=IIIF.Manifest.Serializer.Net.TextGranularity&version=3.0.17
IIIF.Manifest.Serializer.Net
Version-aware .NET models and serializers for IIIF Presentation API resources, with support for legacy 2.x JSON and modern Presentation API 3.0 output.
The core package targets netstandard2.1, uses Newtonsoft.Json, and exposes a fluent object model for building,
reading, converting, and serializing IIIF manifests, collections, canvases, annotation pages, annotations, content
resources, image services, and related IIIF service payloads.
Status
- Package version:
3.0.13fromDirectory.Build.props(core and extension packages). - Core target framework:
netstandard2.1. - Extension target framework:
netstandard2.1. - Test and example project target framework:
net10.0. - Checked-in coverage summary: about 82% line coverage (core + extension packages only).
- Test suite: 557 unit tests (xUnit + AwesomeAssertions) plus 8 architecture tests (NetArchTest.Rules), all passing.
- Documentation: every source folder under
src//extensions/now has a synchronized, source-derived API-reference README underdocs/(see Documentation below); it is current, not lagging.
What It Supports
- IIIF Presentation API 2.0, 2.1, and 3.0 version-aware read/write paths.
Manifest,Collection,Canvas,Range/Structure,AnnotationPage,Annotation, and standaloneAnnotationCollection.- Computed compatibility views for legacy 2.x shapes such as
sequences,images,otherContent,license,attribution,within, anddescription. - 3.0-native concepts such as
items,behavior,rights,requiredStatement,partOf,summary,provider,homepage,thumbnail,rendering,seeAlso,placeholderCanvas, andstart. - W3C-style annotation bodies and targets, including
TextualBody,Choice, multiple bodies, multiple targets,SpecificResource, and selectors. - IIIF Image API service descriptors, including tiles, sizes, preferred/extra formats, extra qualities/features, and
standalone
info.jsonserialization. - IIIF Auth 1.0 and Auth 2.0 service models, including Auth 2.0 probe/access/token/logout services and response payloads.
- IIIF Content Search 2.0 service and response models.
- IIIF Change Discovery 1.0 ordered collection/page and activity models.
- IIIF Content State 1.0 objects and
iiif-contentbase64url encode/decode helpers. - Opt-in, version-aware validation for manifests, collections, and manifest JSON.
- Recursive object-graph change tracking, including collection changes and manifest delta envelopes.
- Extension packages for navPlace, Georeference, and Text Granularity.
- A cookbook example project with faithful C# reconstructions of 71 real IIIF Cookbook recipes.
System.Text.Jsoninterop forManifest/Collection/AnnotationCollection/ContentState: each carries a bridging[JsonConverter]soSystem.Text.Json.JsonSerializer.Serialize/Deserialize(and ASP.NET Core's default (de)serialization) produce the same correct IIIF JSON asIiifSerializer, with no extra configuration.
Standards Coverage
| Area | Current coverage |
|---|---|
| Presentation API | 2.0, 2.1, and 3.0 manifests and collections, plus 3.0 annotation collections. |
| W3C Annotation model | Annotation pages, annotation collections, multiple bodies, multiple targets, textual bodies, choices, specific resources, selectors, stylesheet, and timeMode. |
| Image API | Embedded service descriptors, tiles, sizes, dimensions, preferred/extra formats, qualities, features, protocol, and standalone info.json. |
| Auth API | Auth 1.0 service shape and Auth 2.0 probe/access/token/logout services plus response payloads. |
| Content Search API | Search/autocomplete services and response/result models. |
| Change Discovery API | Ordered collections, ordered collection pages, activities, actors, targets, datasets, rights, and paging. |
| Content State API | Content-state annotation objects, targets, point selectors, and iiif-content codec helpers. |
| Extensions | navPlace, Georeference, and Text Granularity packages. |
Projects
| Path | Purpose |
|---|---|
src/IIIF.Manifest.Serializer.Net |
Core library and version-aware serializer. |
extensions/IIIF.Manifest.Serializer.Net.NavPlace |
navPlace / GeoJSON-LD extension types. |
extensions/IIIF.Manifest.Serializer.Net.Georeference |
Georeference annotation, target, selector, and transformation types. |
extensions/IIIF.Manifest.Serializer.Net.TextGranularity |
Text Granularity extension values and helpers. |
examples/IIIF.Manifest.Serializer.Net.Cookbook |
IIIF Cookbook recipe builders. |
examples/IIIF.Manifest.Serializer.Net.Examples |
Smaller demo catalog. |
tests/IIIF.Manifest.Serializer.Net.Tests |
xUnit coverage for serializers, compatibility views, services, extensions, and examples. |
tests/IIIF.Manifest.Serializer.Net.ArchTests |
NetArchTest.Rules checks enforcing namespace layering (e.g. Shared/Properties must not depend on Nodes) and conventions (e.g. Helpers types must be static). |
docs/SDK_VERSIONING_GUIDE.md |
Detailed implementation and design history for the multi-version model. |
docs/SDK_FIRST_VERSION_IMPLEMENTATION_GUIDE.md |
Target architecture and staged implementation plan for the first stable SDK version. |
Architecture
IiifSerializer is a partial facade. The main IiifSerializer.cs file keeps the public Serialize/Deserialize
overloads and version dispatch, while resource-specific read/write logic lives in focused partial files:
IiifSerializer.Manifest.csIiifSerializer.Collection.csIiifSerializer.Canvas.csIiifSerializer.Range.csIiifSerializer.Annotation.csIiifSerializer.AnnotationCollection.csIiifSerializer.NodeExtras.csIiifSerializer.Metadata.csIiifSerializer.Provider.csIiifSerializer.Service.csIiifSerializer.ImageLikeResources.csIiifSerializer.LinkResources.csIiifSerializer.Helpers.cs
The model uses fluent mutation methods backed by TrackableObject<T>. Additional/extension properties are bridged
through JsonExtensionData, allowing extension payloads such as navPlace, Georeference, and Text Granularity data to
survive JSON round trips.
Quick Start
Install the core package:
dotnet add package IIIF.Manifest.Serializer.Net
Install only the extension packages your application uses:
dotnet add package IIIF.Manifest.Serializer.Net.NavPlace
dotnet add package IIIF.Manifest.Serializer.Net.Georeference
dotnet add package IIIF.Manifest.Serializer.Net.TextGranularity
All four packages use the version in Directory.Build.props; extension packages reference the
matching core package version when packed.
using IIIF.Manifests.Serializer;
using IIIF.Manifests.Serializer.Nodes;
using IIIF.Manifests.Serializer.Nodes.Contents.Annotation;
using IIIF.Manifests.Serializer.Nodes.Contents.Image.Resource;
using IIIF.Manifests.Serializer.Properties;
using IIIF.Manifests.Serializer.Properties.Services;
var manifest = new Manifest(
"https://example.org/iiif/book/manifest",
new Label("Example Manifest"));
var canvas = new Canvas(
"https://example.org/iiif/book/canvas/p1",
new Label("Page 1"),
height: 1800,
width: 1200);
var image = new ImageResource(
"https://example.org/iiif/book/page1/full/max/0/default.jpg",
"image/jpeg")
.SetHeight(1800)
.SetWidth(1200);
image.AddService(new Service(
"http://iiif.io/api/image/3/context.json",
"https://example.org/iiif/book/page1",
"level1"));
canvas.AddAnnotation(new Annotation(
"https://example.org/iiif/book/annotation/p1-image",
image,
canvas.Id));
manifest
.AddItem(canvas)
.SetRights(Rights.CcBy)
.SetRequiredStatement(new RequiredStatement(
new Label("Attribution"),
new Description("Provided by Example Library")));
var v3Json = IiifSerializer.Serialize(manifest);
var v2Json = IiifSerializer.Serialize(
manifest,
new IiifSerializerOptions(IiifPresentationVersion.V2_1));
var parsed = IiifSerializer.DeserializeManifest(v3Json);
IiifSerializerOptions.Default writes Presentation API 3.0. Use IiifPresentationVersion.V2_0 or
IiifPresentationVersion.V2_1 when a legacy output shape is required.
Version-Aware Model
The library stores most resources in a 3.0-shaped model and exposes legacy 2.x properties as compatibility views. For example:
Manifest.Itemsis the preferred canvas ordering;Manifest.Sequencesis a computed legacy view.Canvas.ItemsholdsAnnotationPage/Annotation;Canvas.Images,Audios, andVideosare computed legacy views.Rights,RequiredStatement,PartOf, andSummaryare preferred;License,Attribution,Within, andDescriptionremain readable legacy views.- Legacy mutation APIs are marked obsolete with compile-time errors where there is a 3.0 replacement.
This lets callers read old manifests, work with the current model, and write either 2.x or 3.0 JSON.
Serializer Entry Points
IiifSerializer.Serialize(manifest);
IiifSerializer.Serialize(manifest, new IiifSerializerOptions(IiifPresentationVersion.V2_1));
IiifSerializer.DeserializeManifest(json);
IiifSerializer.Serialize(collection);
IiifSerializer.DeserializeCollection(json);
IiifSerializer.Serialize(annotationCollection);
IiifSerializer.DeserializeAnnotationCollection(json);
Version detection is handled by IiifPresentationVersionDetector using context, type, and structural cues.
Alternatively, since Manifest/Collection/AnnotationCollection/ContentState each carry a
bridging System.Text.Json converter, plain System.Text.Json.JsonSerializer works too and
produces identical output - no IiifSerializer call, no converter registration required:
using System.Text.Json;
string json = JsonSerializer.Serialize(manifest); // same JSON as IiifSerializer.Serialize(manifest)
var parsed = JsonSerializer.Deserialize<Manifest>(json)!; // version auto-detected, same as DeserializeManifest
Annotation and Resource Modeling
The current annotation model covers the common Presentation 3.0/W3C Annotation shapes:
Annotation.Bodyfor a single body andAnnotation.Bodiesfor sibling bodies.Annotation.Targetfor a single target andAnnotation.Targetsfor multi-target annotations.AnnotationTargetfor bare URI targets, typed resource references, and SpecificResource selectors.TextualBodyfor inline text,Choicefor mutually exclusive alternatives, andSpecificResourcefor selected or styled sources.- Selectors:
FragmentSelector,PointSelector,ImageApiSelector, andSvgSelector. BaseResourceJsonConverterfor polymorphic body dispatch across image, audio, video, textual, embedded, choice, specific-resource, and registered extension resource types.
Extensions
The extension projects add spec-specific types and fluent helpers:
- navPlace:
NavPlace,Feature,Geometry, geometry collections, coordinates, andSetNavPlace. - Georeference: georeferencing annotations, SVG selectors, targets, resource coordinates, and polynomial/thin-plate-spline transformations.
- Text Granularity:
page,block,paragraph,line,word, andglyph.
All three extension projects target netstandard2.1 and reference the core package.
Cookbook Examples
The cookbook project is organized into recipe-set classes:
FoundationRecipesCanvasAndStructureRecipesCollectionAndChoiceRecipesMediaVariationRecipesLinkingAndOperaRecipesDescriptivePropertiesRecipesProviderAndTaggingRecipesAnnotationCollectionRecipesAdvancedCompositionRecipes
CookbookCatalog.GetAll() returns the complete catalog as ExampleDefinition entries. Tests round-trip manifest and
collection examples through both 2.1 and 3.0 serializer paths.
The catalog excludes cookbook folders that do not contain manifest JSON of their own. The implemented recipe sets are intended to exercise the serializer surface, not just provide snippets.
Demo Catalog
examples/IIIF.Manifest.Serializer.Net.Examples contains a smaller DemoCatalog with examples for:
- Search and access services.
- Deep zoom image services.
- Paged books.
- Collection browsing.
- Legacy annotation list serialization.
- Map/navPlace data.
Build and Test
The repository uses the .NET SDK configured by global.json:
dotnet restore IIIF.Manifest.Serializer.Net.slnx
dotnet build IIIF.Manifest.Serializer.Net.slnx
dotnet test tests/IIIF.Manifest.Serializer.Net.Tests/IIIF.Manifest.Serializer.Net.Tests.csproj
dotnet test tests/IIIF.Manifest.Serializer.Net.ArchTests/IIIF.Manifest.Serializer.Net.ArchTests.csproj
Run the cookbook examples:
dotnet run --project examples/IIIF.Manifest.Serializer.Net.Cookbook/IIIF.Manifest.Serializer.Net.Cookbook.csproj
Collect coverage:
dotnet test tests/IIIF.Manifest.Serializer.Net.Tests/IIIF.Manifest.Serializer.Net.Tests.csproj `
--collect:"XPlat Code Coverage" `
--settings tests/IIIF.Manifest.Serializer.Net.Tests/coverlet.runsettings `
--results-directory ./coverage-raw
The checked-in coverage summary currently reports line coverage around 82% (core and extension
packages only - demo/test harness assemblies are excluded, see
tests/IIIF.Manifest.Serializer.Net.Tests/coverlet.runsettings).
Packaging
The package version is defined in Directory.Build.props and is currently 3.0.13. The core package metadata
describes the package as:
Version-aware IIIF Presentation API manifest serializer using Newtonsoft.Json.
| Package | NuGet | Documentation |
|---|---|---|
IIIF.Manifest.Serializer.Net |
Core package | Project guide |
IIIF.Manifest.Serializer.Net.NavPlace |
navPlace package | navPlace API |
IIIF.Manifest.Serializer.Net.Georeference |
Georeference package | Georeference API |
IIIF.Manifest.Serializer.Net.TextGranularity |
Text Granularity package | Text Granularity API |
All four packages are consumed straight from nuget.org - there is no
NuGet.Config in this repository and no private/custom feed to configure.
This repository's package version is managed by the root Directory.Build.props. Folder-scoped
Directory.Packages.props files manage third-party dependency versions.
See the release hygiene guide for how CI, SAST, patch management, and NuGet publishing fit together, and the exact commands to smoke-test a release locally before tagging.
Documentation
Project guide - installation, quick start, multi-version serialization, Newtonsoft.Json/System.Text.Json interop, the object model, the
IiifSerializerarchitecture, services, extension packages, the Cookbook's Strategy+Registry design, and testing.Versioning and architecture guide - the authoritative design record: the 2.x↔3.0 property mapping table, the Obsolete-tagging convention, and the full milestone history (multi-version reshape, extended standards coverage, the Cookbook catalog, the Facade/Strategy/Registry structural refactor, and the System.Text.Json interop bridge).
Change tracking guide - the pull-based, EF Core-style object-graph change tracker:
HasChanges/GetChanges()/ClearChanges()/AcceptChanges(), parent/child propagation, collection add/remove semantics, and changed-only manifest/delta output viaManifest.GetChangedManifest()/GetChangeSet().API reference - every folder under
src/IIIF.Manifest.Serializer.Net/andextensions/*has its own README underdocs/, mirroring the source tree 1:1 (types, members, attributes, Mermaid diagrams, package dependencies). Two-level catalog below; each area links to its own deeper nesting.Area Types Files Diagrams Attributes 10 10 ✓ Change tracking 4 4 ✓ Extensions 22 23 ✓ NavPlace 9 10 ✓ Georeference 11 11 ✓ TextGranularity 2 2 ✓ Helpers 6 6 ✓ Nodes 34 34 ✓ Properties 65 65 ✓ Shared 39 36 ✓ System.Text.Json interop 4 4 ✓ Validation 5 6 ✓ More than 200 public API types across 219 source files are documented in 51 source folders. See the documentation catalog for the fully expanded catalog (every subfolder, not just each area's direct children) and the coverage audit.
When changing serializer behavior, update tests and prefer checking the real JSON shape through IiifSerializer rather
than relying on direct JsonConvert output. Direct JsonConvert is still used for legacy compatibility surfaces and
for specific standalone payloads, but the version-aware serializer is the intended public entry point for manifests,
collections, and annotation collections. When adding a genuinely new 3.0-native property, back any legacy 2.x equivalent
with a computed read-only view rather than the other way around (see docs/SDK_VERSIONING_GUIDE.md §3-4).
License
See LICENSE.
| 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 | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- IIIF.Manifest.Serializer.Net (>= 3.0.17)
- Newtonsoft.Json (>= 13.0.4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
- IIIF.Manifest.Serializer.Net: stop excluding Tests/ArchTests from solution-level Release builds\n- IIIF.Manifest.Serializer.Net: close EF Core collection-mapping hazards, add [NotMapped] to legacy views\n- IIIF.Manifest.Serializer.Net: mark every deprecated legacy member [Obsolete], not just mutators\n- IIIF.Manifest.Serializer.Net: split collection tombstones from live items, fix change-tracking bugs, cut hot-path allocations\n- ci: restrict publish-nuget.yml to the main branch\n- feat: add EF Core-compatible parameterless constructors to all model types\n- fix: harden trackable change subscriptions\n- docs: synchronize API and NuGet documentation\n- refactor: reorganize trackable infrastructure and seal leaf types\n- refactor: unify descriptor-based change tracking\n- fix: update GitHub token secret reference in NuGet publish workflow\n- feat: add deep collection change tracking\n- Switch NuGet publish workflow to classic API key\n- Use secret for NuGet user in publish workflow\n- Replace NUGET_USER secret with hardcoded username\n- Fix smoke test package path in NuGet publish\n- Switch NuGet release bump to patch version\n- Use reusable-ci for NuGet release workflow\n- Expand release workflow job permissions\n- Grant contents write in release workflow\n- Consolidate release CI to reusable workflow\n- Reuse shared security workflows\n- Clean up Claude commands and refresh .gitignore\n- Automate manual NuGet release preparation\n- [IIIF.Manifest.Serializer.Net#23] SDK Change Tracking: EF Core-style object graph change tracker and changed-only manifest output\n- [IIIF.Manifest.Serializer.Net#13] Refactor solution file: standardize project path formatting and organize folder structure\n- [IIIF.Manifest.Serializer.Net#13] SDK Phase 7: add validation layer and release-hardening checks\n- [IIIF.Manifest.Serializer.Net#12] SDK Research: upstream IIIF standards and awesome-iiif coverage matrix\n- [IIIF.Manifest.Serializer.Net#11] SDK Phase 6B: add demo scenarios, fix embedded-service gap in IiifSerializer\n- [IIIF.Manifest.Serializer.Net#10] SDK Phase 6A: verify cookbook recipe parity, add coverage matrix