RDF Vocabulary to Dart - Type-safe RDF for Dart
Overview
rdf_vocabulary_to_dart
is a Dart build tool that transforms RDF vocabularies into type-safe Dart code. Built on top of rdf_core, it enables Dart developers to work with RDF data using familiar, strongly-typed patterns.
The tool generates two complementary sets of classes:
-
Vocabulary Classes - Each vocabulary (like Schema.org, FOAF, etc.) gets a dedicated class containing constants for all terms within that vocabulary, ideal for developers already familiar with RDF.
-
RDF Class-Specific Classes - For each RDF class within a vocabulary (like schema:Person, foaf:Agent), a dedicated Dart class is generated containing properties from that class and all its superclasses.
This dual approach makes RDF concepts accessible to both RDF experts and Dart developers new to the semantic web.
Part of a whole family of projects
If you are looking for more rdf-related functionality, have a look at our companion projects:
- basic graph classes as well as turtle/jsonld/n-triple encoding and decoding: rdf_core
- encode and decode rdf/xml format: rdf_xml
- easy-to-use constants for many well-known vocabularies: rdf_vocabularies
- map Dart Objects ↔️ RDF: rdf_mapper
Features
- Type-Safe RDF Terms: Access vocabulary terms as constants with proper typing
- Intelligent Code Generation: Automatic handling of namespaces, prefixes, and term resolution
- Cross-Vocabulary Integration: Properties from related vocabularies are properly prefixed and included
- IDE Completion: Discover available terms through IDE autocompletion
- Inheritance Support: Class-specific objects include properties from parent classes
- Comprehensive Vocabulary Coverage: Works with any RDF vocabulary accessible via URL or local file
- Full Platform Compatibility: While pub.dev shows "no support for web" (because this is a build_runner tool used only during build time), the generated code is 100% compatible with all platforms including web, Flutter, and native Dart
Getting Started
Installation
Add these dependencies to your pubspec.yaml
:
dependencies:
rdf_core: ^0.8.1 # Core library for working with RDF data
dev_dependencies:
build_runner: ^2.4.0 # Runs the code generator
rdf_vocabulary_to_dart: ^0.8.0 # The code generator
Configuration
- Create a configuration file in your project (e.g.,
lib/src/vocab/vocabulary_sources.vocab.json
):
{
"vocabularies": {
"schema": {
"type": "url",
"namespace": "https://schema.org/"
},
"foaf": {
"type": "url",
"namespace": "http://xmlns.com/foaf/0.1/"
},
"custom": {
"type": "file",
"namespace": "http://example.org/myvocab#",
"filePath": "lib/src/vocab/custom_vocab.ttl"
}
}
}
- Configure
build.yaml
in your project root:
targets:
$default:
builders:
rdf_vocabulary_to_dart|rdf_to_dart_generator:
enabled: true
options:
vocabulary_config_path: "lib/src/vocab/vocabulary_sources.vocab.json"
output_dir: "lib/src/vocab/generated"
- Run the code generator:
dart run build_runner build
Usage Examples
Using Vocabulary Classes
import 'package:rdf_core/rdf_core.dart';
import 'package:your_package/src/vocab/generated/schema.dart';
import 'package:your_package/src/vocab/generated/foaf.dart';
// Create a triple using vocabulary constants
final triple = Triple(
IriTerm('http://example.org/john'),
Schema.name, // https://schema.org/name
LiteralTerm.string('John Doe')
);
// Use vocabulary terms in queries or graph operations
final graph = RdfGraph(triples: [triple]);
final nameQuery = graph.find(
subject: null,
predicate: Schema.name,
object: null
);
Using Class-Specific Classes
import 'package:rdf_core/rdf_core.dart';
import 'package:your_package/src/vocab/generated/schema_person.dart';
void createPersonTriples(IriTerm person) {
// SchemaPerson contains all properties related to the schema:Person class
// including inherited properties from parent classes
final graph = RdfGraph(triples: [
// Properties from other vocabularies are properly prefixed, like e.g. type from rdf which you need to declare this to be a schema:Person.
Triple(person, SchemaPerson.rdfType, SchemaPerson.classIri),
Triple(person, SchemaPerson.name, LiteralTerm.string('Jane Doe')),
Triple(person, SchemaPerson.email, LiteralTerm.string('jane@example.com')),
]);
}
Understanding the Generated Code
For a vocabulary like Schema.org, the generator produces:
- Schema.dart - Contains all terms from the Schema.org vocabulary:
/// Schema.org Vocabulary
class Schema {
Schema._();
/// Base namespace for Schema.org
static const namespace = 'https://schema.org/';
/// A person (alive, dead, undead, or fictional).
static const Person = IriTerm('https://schema.org/Person');
/// The name of the item.
static const name = IriTerm('https://schema.org/name');
// ... many more terms
}
- SchemaPerson.dart - Contains properties specific to the schema:Person class:
/// Properties for the Schema.org Person class
class SchemaPerson {
SchemaPerson._();
/// The RDF class IRI
static const classIri = Schema.Person;
/// The name of the person.
static const name = Schema.name;
/// Email address.
static const email = Schema.email;
/// A person known by this person (from FOAF vocabulary, if Schema.Person properly inherits from Foaf.Person).
static const foafKnows = FOAF.knows;
// ... including inherited properties from parent classes
}
Configuration Options
Vocabulary Source Configuration
Each vocabulary in your configuration file can have these properties:
Property | Description | Required |
---|---|---|
type |
Either "url" for remote vocabularies or "file" for local files | Yes |
namespace |
The base IRI namespace of the vocabulary | Yes |
source |
For "url" type: URL to fetch the vocabulary from; for "file" type: path to local file | Yes (for "file" type), No (for "url" type, defaults to namespace) |
parsingFlags |
Array of string flags passed to the TurtleCodec when decoding Turtle files | No |
generate |
Boolean indicating if this vocabulary should be processed (defaults to true) | No |
contentType |
Explicit content type to use for the vocabulary source, overriding auto-detection | No |
skipDownload |
Boolean flag to deliberately skip a vocabulary (defaults to false) | No |
skipDownloadReason |
Text explanation for why a vocabulary is skipped | No |
Build Configuration
The build.yaml
file supports these options:
Option | Description | Default |
---|---|---|
vocabulary_config_path |
Path to vocabulary configuration JSON | "lib/src/vocab/vocabulary_sources.vocab.json" |
output_dir |
Directory where generated files are placed | "lib/src/vocab/generated" |
How It Works
- Loading Configuration: The builder reads your vocabulary configuration
- Fetching Vocabularies: For each vocabulary, retrieves content from URL or file
- Decode RDF: Processes the vocabulary data using rdf_core decoders
- Cross-Vocabulary Resolution: Identifies relationships between vocabularies
- Code Generation: Produces Dart classes for each vocabulary and RDF class
- Indexing: Creates an index file for easy importing
Advanced Use Cases
Working with Multiple Vocabularies
You can define multiple vocabularies in your configuration file, and they will be automatically cross-referenced when generating class-specific modules.
Custom RDF Vocabularies
For domain-specific RDF vocabularies, use the "file" type and provide a local Turtle file:
{
"vocabularies": {
"myapp": {
"type": "file",
"namespace": "http://example.org/myapp#",
"filePath": "lib/src/vocab/myapp.ttl"
}
}
}
Integration with RDF Data Sources
The generated code works seamlessly with rdf_core's decoders and encoders, making it easy to process RDF data from various sources:
import 'package:rdf_core/rdf_core.dart';
import 'package:your_package/src/vocab/generated/schema.dart';
final turtleContent = ...;
final graph = await turtle.decode(turtleContent);
// Query using vocabulary terms
final people = graph.find(
subject: null,
predicate: Rdf.type,
object: Schema.Person
);
for (final person in people) {
final names = graph.find(
subject: person.subject,
predicate: Schema.name,
object: null
);
// Process results...
}
🛣️ Roadmap / Next Steps
- More and better tests
- Ensure that we stick to dart file name conventions for lowerCamelCase prefixes, e.g. do not write schemaHttp.dart files but schema_http.dart instead.
- Improve documentation
- Include an example
- Solve the issue with "unresolved doc reference" in the generated documentation
🤝 Contributing
Contributions, bug reports, and feature requests are welcome!
- Fork the repo and submit a PR
- See CONTRIBUTING.md for guidelines
- Join the discussion in GitHub Issues
🤖 AI Policy
This project is proudly human-led and human-controlled, with all key decisions, design, and code reviews made by people. At the same time, it stands on the shoulders of LLM giants: generative AI tools are used throughout the development process to accelerate iteration, inspire new ideas, and improve documentation quality. We believe that combining human expertise with the best of AI leads to higher-quality, more innovative open source software.
© 2025 Klas Kalaß. Licensed under the MIT License.
Libraries
- rdf_vocabulary_to_dart
- This library exposes the builder factory for generating Dart classes from RDF vocabulary namespace IRIs.