Frank.Rdf
7.3.3
dotnet add package Frank.Rdf --version 7.3.3
NuGet\Install-Package Frank.Rdf -Version 7.3.3
<PackageReference Include="Frank.Rdf" Version="7.3.3" />
<PackageVersion Include="Frank.Rdf" Version="7.3.3" />
<PackageReference Include="Frank.Rdf" />
paket add Frank.Rdf --version 7.3.3
#r "nuget: Frank.Rdf, 7.3.3"
#:package Frank.Rdf@7.3.3
#addin nuget:?package=Frank.Rdf&version=7.3.3
#tool nuget:?package=Frank.Rdf&version=7.3.3
Frank.Rdf
An rdf { } computation expression for hand-authoring RDF triples across one or more resources, serialized to JSON-LD in expanded form.
Zero ASP.NET Core dependency — no ProjectReference to Frank, no FrameworkReference to Microsoft.AspNetCore.App; the only NuGet dependency is dotNetRdf.Core. It builds and serializes documents; it has no opinion on how a handler returns the result.
Installation
dotnet add package Frank.Rdf
Example
open System
open Frank.Rdf
let players = Node.Iri "https://example.org/games/1#players"
let anonymousReview = Node.blank () // no natural IRI -- minted fresh, GUID-backed
let gameDoc =
rdf {
prefix "schema" "https://schema.org/"
about (
describe (Node.Iri "https://example.org/games/1") {
typ "schema:Game"
propertyString "schema:name" "Tic-tac-toe"
propertyInt "schema:numberOfPlayers" 2
propertyBool "schema:isFree" true
propertyDateTime "schema:datePublished" (DateTimeOffset(1952, 1, 1, 0, 0, 0, TimeSpan.Zero))
propertyNode "schema:sameAs" (Node.Iri "http://www.wikidata.org/entity/Q210339")
propertyNode "schema:review" anonymousReview
}
)
about (describe anonymousReview { propertyString "schema:reviewBody" "A timeless classic." })
}
Doc.toJsonLd gameDoc
describe/about mirrors handler { }/get: describe subject { ... } runs to completion on its own, producing a plain Description, and about absorbs it into the surrounding rdf { } document — the same two-CE composition pattern Frank core already uses for handler { } feeding resource { }'s get. A bare triple subject predicate value operation is also available for one-off statements.
Node.blank () mints an anonymous node for values with no natural IRI (like the review above) — each call is GUID-backed, so blank nodes minted by two independently-built Docs never collide when merged via Doc.merge/includeDoc.
Available Operations
prefix "name" "uri"- Declares a CURIE namespace mappingabout (describe subject { ... })- Absorbs aDescriptionbuilt by a nesteddescribe { }blocktriple subject predicate value- Asserts a single statement directlyincludeDoc otherDoc- Merges another independently-builtDocin (same asDoc.merge)typ "prefix:Type"- Assertsrdf:typepropertyString/propertyInt/propertyBool/propertyDateTime/propertyNode- Asserts a property, picked by the value's type (five distinct operations rather than one overloadedproperty, since F#'s custom-operation overload resolution can't reliably disambiguate by argument type across calls in the same block)Node.blank ()- Mints a fresh, GUID-backed blank node for a subject/object with no natural IRI
Serializing
Doc.toGraph doc- Builds aVDS.RDF.GraphDoc.writeJsonLd doc writer- Streams expanded-form JSON-LD into aSystem.IO.TextWriter(synchronous, flexible for any stream)Doc.writeJsonLdAsync doc bufferWriter- Streams expanded-form JSON-LD asynchronously into anIBufferWriter<byte>(e.g.HttpResponse.BodyWriter) — best for response streaming, encodes UTF8 directly to the buffer with no intermediate string allocationDoc.toJsonLd doc- Convenience wrapper returning the JSON-LD as astring
Output is always expanded-form JSON-LD: no @context, every predicate and type expanded to its absolute IRI. There is no compact-form option.
Choosing a serialization method
- Use
writeJsonLdAsyncwhen streaming to HTTP responses (most efficient, async-friendly) - Use
writeJsonLdwhen you have aTextWriterfrom a third-party API or need flexibility - Use
toJsonLdfor testing, debugging, or when the full document fits in memory
Related Packages
Has no dependency on Frank, but is designed to serve JSON-LD documents from Frank resources — see sample/Frank.Rdf.Sample for a runnable demonstration, including Doc.merge folding shared facts (a publisher record) into each per-resource document.
See the project repository for the complete guide and sample applications.
License
| 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
- dotNetRdf.Core (>= 3.5.1)
- FSharp.Core (>= 10.1.302)
-
net8.0
- dotNetRdf.Core (>= 3.5.1)
- FSharp.Core (>= 10.1.302)
-
net9.0
- dotNetRdf.Core (>= 3.5.1)
- FSharp.Core (>= 10.1.302)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Frank.Rdf:
| Package | Downloads |
|---|---|
|
Frank.Validation
Hand-authored SHACL Core validation for Frank resources, built on Frank.Rdf |
|
|
Frank.Provenance
PROV-O provenance recording and querying for Frank resources, built on Frank.Rdf |
GitHub repositories
This package is not used by any popular GitHub repositories.
### New in 7.3.3 (Released 2026-08-10)
**Frank.Rdf - Async IBufferWriter Streaming**
- **New: `Doc.writeJsonLdAsync doc bufferWriter`** — async overload that writes JSON-LD expanded-form directly to an `IBufferWriter<byte>` (e.g. `HttpResponse.BodyWriter`/`PipeWriter`), without intermediate string allocation or copying. Encodes UTF8 directly to the buffer for maximum efficiency in response streaming. Completes after serialization and flushing to the buffer.
- **Recommended for response streaming:** `writeJsonLdAsync` is the preferred method when serving JSON-LD from a Frank handler over HTTP. Streaming directly to `PipeWriter` avoids `AllowSynchronousIO` requirements and eliminates intermediate buffering layers that `StreamWriter` would introduce.
- **Three serialization options now available:** Use `writeJsonLdAsync` for HTTP responses (most efficient), `writeJsonLd` for flexibility with any `TextWriter`, and `toJsonLd` for testing/debugging.
- **Sample updated:** `sample/Frank.Rdf.Sample` demonstrates `Doc.writeJsonLdAsync` streaming the `application/ld+json` representation directly to the response body via `negotiate { }` content negotiation.
- **Test coverage:** comprehensive test cases for `writeJsonLdAsync` including single and multi-subject documents, language-tagged strings, and round-trip parsing.