lutaml-model 0.8.4 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/dependent-tests.yml +3 -1
- data/.rubocop.yml +18 -0
- data/.rubocop_todo.yml +12 -18
- data/Gemfile +2 -0
- data/README.adoc +114 -2
- data/docs/_guides/index.adoc +18 -0
- data/docs/_guides/jsonld-serialization.adoc +217 -0
- data/docs/_guides/rdf-serialization.adoc +344 -0
- data/docs/_guides/turtle-serialization.adoc +224 -0
- data/docs/_pages/serialization_adapters.adoc +31 -0
- data/docs/_references/index.adoc +1 -0
- data/docs/_references/rdf-namespaces.adoc +243 -0
- data/docs/index.adoc +3 -2
- data/lib/lutaml/jsonld/adapter.rb +23 -0
- data/lib/lutaml/jsonld/context.rb +69 -0
- data/lib/lutaml/jsonld/term_definition.rb +39 -0
- data/lib/lutaml/jsonld/transform.rb +174 -0
- data/lib/lutaml/jsonld.rb +23 -0
- data/lib/lutaml/model/format_registry.rb +10 -1
- data/lib/lutaml/model/serialize/format_conversion.rb +17 -1
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model.rb +6 -0
- data/lib/lutaml/rdf/error.rb +7 -0
- data/lib/lutaml/rdf/iri.rb +44 -0
- data/lib/lutaml/rdf/language_tagged.rb +11 -0
- data/lib/lutaml/rdf/literal.rb +62 -0
- data/lib/lutaml/rdf/mapping.rb +71 -0
- data/lib/lutaml/rdf/mapping_rule.rb +35 -0
- data/lib/lutaml/rdf/member_rule.rb +13 -0
- data/lib/lutaml/rdf/namespace.rb +58 -0
- data/lib/lutaml/rdf/namespace_set.rb +69 -0
- data/lib/lutaml/rdf/namespaces/dcterms_namespace.rb +12 -0
- data/lib/lutaml/rdf/namespaces/owl_namespace.rb +12 -0
- data/lib/lutaml/rdf/namespaces/rdf_namespace.rb +14 -0
- data/lib/lutaml/rdf/namespaces/rdfs_namespace.rb +12 -0
- data/lib/lutaml/rdf/namespaces/skos_namespace.rb +12 -0
- data/lib/lutaml/rdf/namespaces/xsd_namespace.rb +12 -0
- data/lib/lutaml/rdf/namespaces.rb +14 -0
- data/lib/lutaml/rdf/transform.rb +36 -0
- data/lib/lutaml/rdf.rb +19 -0
- data/lib/lutaml/turtle/adapter.rb +35 -0
- data/lib/lutaml/turtle/mapping.rb +7 -0
- data/lib/lutaml/turtle/transform.rb +158 -0
- data/lib/lutaml/turtle.rb +22 -0
- data/spec/lutaml/integration/edge_cases_spec.rb +109 -0
- data/spec/lutaml/integration/multi_format_spec.rb +106 -0
- data/spec/lutaml/integration/round_trip_spec.rb +170 -0
- data/spec/lutaml/jsonld/adapter_spec.rb +46 -0
- data/spec/lutaml/jsonld/context_spec.rb +114 -0
- data/spec/lutaml/jsonld/term_definition_spec.rb +55 -0
- data/spec/lutaml/jsonld/transform_spec.rb +211 -0
- data/spec/lutaml/rdf/graph_serialization_spec.rb +137 -0
- data/spec/lutaml/rdf/iri_spec.rb +73 -0
- data/spec/lutaml/rdf/literal_spec.rb +98 -0
- data/spec/lutaml/rdf/mapping_spec.rb +164 -0
- data/spec/lutaml/rdf/member_rule_spec.rb +17 -0
- data/spec/lutaml/rdf/namespace_set_spec.rb +115 -0
- data/spec/lutaml/rdf/namespace_spec.rb +241 -0
- data/spec/lutaml/rdf/rdf_transform_spec.rb +82 -0
- data/spec/lutaml/turtle/adapter_spec.rb +47 -0
- data/spec/lutaml/turtle/mapping_spec.rb +123 -0
- data/spec/lutaml/turtle/transform_spec.rb +273 -0
- metadata +50 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2bc036758cf2a4ac1420e14fc6be130730410ab183cd002ced260bdbf08793eb
|
|
4
|
+
data.tar.gz: 1dfc1b473558992eb1481a535d86c1688313951530762c9317af90413028032e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8a4cec37c9acf840b89f6f363aecb8e7bf1a2237d962c6fa8bbe4d4422848cc63812efbd86369780c0e7d26470ff9f220284d062af86b9ebf7f621f3f8e579cb
|
|
7
|
+
data.tar.gz: a48c77e4d99c97fb8cc6fa6793a45b2ba12b79196d9340a23bf4d43a1090c84c05a2402a84ab52792b105713c78caa51f58cfcb141cf79459b06c929adac11b5
|
|
@@ -19,6 +19,8 @@ on:
|
|
|
19
19
|
|
|
20
20
|
jobs:
|
|
21
21
|
rake:
|
|
22
|
-
uses: metanorma/ci/.github/workflows/dependent-rake.yml@
|
|
22
|
+
uses: metanorma/ci/.github/workflows/dependent-rake.yml@fix/add-pat-token
|
|
23
23
|
with:
|
|
24
24
|
command: bundle exec rspec
|
|
25
|
+
secrets:
|
|
26
|
+
pat_token: ${{ secrets.LUTAML_CI_PAT_TOKEN }}
|
data/.rubocop.yml
CHANGED
|
@@ -24,3 +24,21 @@ Style/OneClassPerFile:
|
|
|
24
24
|
- Exclude
|
|
25
25
|
Exclude:
|
|
26
26
|
- 'spec/**/*'
|
|
27
|
+
|
|
28
|
+
RSpec/EmptyExampleGroup:
|
|
29
|
+
inherit_mode:
|
|
30
|
+
merge:
|
|
31
|
+
- Exclude
|
|
32
|
+
Exclude:
|
|
33
|
+
- 'spec/lutaml/jsonld/transform_spec.rb'
|
|
34
|
+
|
|
35
|
+
RSpec/NamedSubject:
|
|
36
|
+
inherit_mode:
|
|
37
|
+
merge:
|
|
38
|
+
- Exclude
|
|
39
|
+
Exclude:
|
|
40
|
+
- 'spec/lutaml/turtle/transform_spec.rb'
|
|
41
|
+
|
|
42
|
+
RSpec/ContextMethod:
|
|
43
|
+
Exclude:
|
|
44
|
+
- 'spec/lutaml/jsonld/transform_spec.rb'
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-05-06
|
|
3
|
+
# on 2026-05-06 13:11:11 UTC using RuboCop version 1.86.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
@@ -11,7 +11,7 @@ Gemspec/RequiredRubyVersion:
|
|
|
11
11
|
Exclude:
|
|
12
12
|
- 'lutaml-model.gemspec'
|
|
13
13
|
|
|
14
|
-
# Offense count:
|
|
14
|
+
# Offense count: 3264
|
|
15
15
|
# This cop supports safe autocorrection (--autocorrect).
|
|
16
16
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
17
17
|
# URISchemes: http, https
|
|
@@ -34,16 +34,10 @@ Lint/ConstantDefinitionInBlock:
|
|
|
34
34
|
Lint/DuplicateBranch:
|
|
35
35
|
Enabled: false
|
|
36
36
|
|
|
37
|
-
# Offense count:
|
|
37
|
+
# Offense count: 3
|
|
38
38
|
Lint/DuplicateMethods:
|
|
39
39
|
Exclude:
|
|
40
40
|
- 'lib/lutaml/xml/mapping.rb'
|
|
41
|
-
- 'spec/lutaml/model/liquid_compatibility_spec.rb'
|
|
42
|
-
- 'spec/lutaml/xml/namespace_no_hoisting_spec.rb'
|
|
43
|
-
- 'spec/lutaml/xml/namespace_scope_declare_spec.rb'
|
|
44
|
-
- 'spec/lutaml/xml/namespace_scope_vcard_spec.rb'
|
|
45
|
-
- 'spec/lutaml/xml/prefix_control_spec.rb'
|
|
46
|
-
- 'spec/lutaml/xml/type_namespace_examples_spec.rb'
|
|
47
41
|
|
|
48
42
|
# Offense count: 1
|
|
49
43
|
# This cop supports safe autocorrection (--autocorrect).
|
|
@@ -116,7 +110,7 @@ Lint/UselessConstantScoping:
|
|
|
116
110
|
- 'lib/lutaml/xml/adapter/nokogiri_adapter.rb'
|
|
117
111
|
- 'lib/lutaml/xml/mapping_rule.rb'
|
|
118
112
|
|
|
119
|
-
# Offense count:
|
|
113
|
+
# Offense count: 355
|
|
120
114
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
121
115
|
Metrics/AbcSize:
|
|
122
116
|
Enabled: false
|
|
@@ -132,23 +126,23 @@ Metrics/BlockLength:
|
|
|
132
126
|
Metrics/BlockNesting:
|
|
133
127
|
Max: 6
|
|
134
128
|
|
|
135
|
-
# Offense count:
|
|
129
|
+
# Offense count: 315
|
|
136
130
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
137
131
|
Metrics/CyclomaticComplexity:
|
|
138
132
|
Enabled: false
|
|
139
133
|
|
|
140
|
-
# Offense count:
|
|
134
|
+
# Offense count: 575
|
|
141
135
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
142
136
|
Metrics/MethodLength:
|
|
143
137
|
Max: 514
|
|
144
138
|
|
|
145
|
-
# Offense count:
|
|
139
|
+
# Offense count: 88
|
|
146
140
|
# Configuration parameters: CountKeywordArgs.
|
|
147
141
|
Metrics/ParameterLists:
|
|
148
142
|
Max: 24
|
|
149
143
|
MaxOptionalParameters: 5
|
|
150
144
|
|
|
151
|
-
# Offense count:
|
|
145
|
+
# Offense count: 264
|
|
152
146
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
153
147
|
Metrics/PerceivedComplexity:
|
|
154
148
|
Enabled: false
|
|
@@ -240,7 +234,7 @@ RSpec/BeforeAfterAll:
|
|
|
240
234
|
RSpec/ContextWording:
|
|
241
235
|
Enabled: false
|
|
242
236
|
|
|
243
|
-
# Offense count:
|
|
237
|
+
# Offense count: 92
|
|
244
238
|
# Configuration parameters: IgnoredMetadata.
|
|
245
239
|
RSpec/DescribeClass:
|
|
246
240
|
Enabled: false
|
|
@@ -251,7 +245,7 @@ RSpec/DescribeMethod:
|
|
|
251
245
|
- 'spec/lutaml/xml/schema/xsd/schema_helper_methods_spec.rb'
|
|
252
246
|
- 'spec/lutaml/xml/serializable_namespace_spec.rb'
|
|
253
247
|
|
|
254
|
-
# Offense count:
|
|
248
|
+
# Offense count: 1234
|
|
255
249
|
# Configuration parameters: CountAsOne.
|
|
256
250
|
RSpec/ExampleLength:
|
|
257
251
|
Max: 68
|
|
@@ -326,7 +320,7 @@ RSpec/MultipleDescribes:
|
|
|
326
320
|
- 'spec/lutaml/xml/namespace_resolution_strategy_spec.rb'
|
|
327
321
|
- 'spec/lutaml/xml/xml_space_type_spec.rb'
|
|
328
322
|
|
|
329
|
-
# Offense count:
|
|
323
|
+
# Offense count: 1442
|
|
330
324
|
RSpec/MultipleExpectations:
|
|
331
325
|
Max: 21
|
|
332
326
|
|
|
@@ -374,7 +368,7 @@ RSpec/RepeatedExampleGroupDescription:
|
|
|
374
368
|
Exclude:
|
|
375
369
|
- 'spec/lutaml/model/mixed_content_spec.rb'
|
|
376
370
|
|
|
377
|
-
# Offense count:
|
|
371
|
+
# Offense count: 40
|
|
378
372
|
# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
|
|
379
373
|
# SupportedInflectors: default, active_support
|
|
380
374
|
RSpec/SpecFilePathFormat:
|
data/Gemfile
CHANGED
|
@@ -12,6 +12,7 @@ gem "base64"
|
|
|
12
12
|
gem "benchmark-ips"
|
|
13
13
|
gem "bigdecimal"
|
|
14
14
|
gem "canon" # , path: "../canon"
|
|
15
|
+
gem "json-ld", "~> 3.3"
|
|
15
16
|
gem "liquid", "~> 5"
|
|
16
17
|
gem "multi_json"
|
|
17
18
|
gem "nokogiri"
|
|
@@ -20,6 +21,7 @@ gem "oj"
|
|
|
20
21
|
gem "openssl", "~> 3.0"
|
|
21
22
|
gem "ox"
|
|
22
23
|
gem "rake"
|
|
24
|
+
gem "rdf-turtle", "~> 3.3"
|
|
23
25
|
gem "rexml"
|
|
24
26
|
gem "rspec"
|
|
25
27
|
gem "rubocop"
|
data/README.adoc
CHANGED
|
@@ -27,7 +27,7 @@ for:
|
|
|
27
27
|
|
|
28
28
|
It provides simple, flexible and comprehensive mechanisms for defining
|
|
29
29
|
information models with attributes and types, and the serialization of them
|
|
30
|
-
to/from serialization formats including JSON, XML, YAML, and
|
|
30
|
+
to/from serialization formats including JSON, XML, YAML, TOML, JSON-LD, and Turtle, as well as
|
|
31
31
|
transformation to other formats like Hash.
|
|
32
32
|
|
|
33
33
|
For serialization formats, it uses an adapter pattern to support multiple
|
|
@@ -48,7 +48,7 @@ link:docs/migration-guides/0-1-0-migrate-from-shale.adoc[Migrating from Shale to
|
|
|
48
48
|
== Features
|
|
49
49
|
|
|
50
50
|
* Define models with attributes and types
|
|
51
|
-
* Serialize and deserialize models to/from JSON, XML, YAML, and
|
|
51
|
+
* Serialize and deserialize models to/from JSON, XML, YAML, TOML, JSON-LD, and Turtle
|
|
52
52
|
* Transform models to other formats like Hash
|
|
53
53
|
* Support for multiple serialization libraries (e.g., `toml-rb`, `tomlib`)
|
|
54
54
|
* Configurable adapters for different serialization formats
|
|
@@ -65,6 +65,7 @@ link:docs/migration-guides/0-1-0-migrate-from-shale.adoc[Migrating from Shale to
|
|
|
65
65
|
* Symmetric OOP architecture for all formats with KeyValueDataModel (see <<keyvaluedatamodel-architecture>>)
|
|
66
66
|
* Parse XSD schemas into Ruby objects for inspection and manipulation (see <<xsd-schema-parsing>>)
|
|
67
67
|
* Reusable XML mapping classes for sharing mappings across models
|
|
68
|
+
* RDF namespace classes and JSON-LD/Turtle format adapters for Linked Data serialization
|
|
68
69
|
* Consolidation mapping: group sibling XML elements into structured model instances (see <<consolidation-mapping>>)
|
|
69
70
|
* Document-level validation framework with composable rules, profiles, and remediation (see <<document-validation-framework>>)
|
|
70
71
|
|
|
@@ -5391,6 +5392,11 @@ Collection serialization formats::
|
|
|
5391
5392
|
`jsonl`::: JSONL (JSON Lines) (see <<mapping-collections>>)
|
|
5392
5393
|
`yamls`::: YAML Stream (multi-document format) (see <<mapping-collections>>)
|
|
5393
5394
|
|
|
5395
|
+
RDF serialization formats::
|
|
5396
|
+
|
|
5397
|
+
`rdf`::: Unified RDF mapping for both JSON-LD and Turtle (see <<mapping-rdf>>)
|
|
5398
|
+
`turtle`::: Turtle (see link:docs/_guides/turtle-serialization.adoc[Turtle Serialization])
|
|
5399
|
+
|
|
5394
5400
|
|
|
5395
5401
|
.Using the `xml`, `hsh`, `json`, `yaml`, `toml` and `key_value` blocks to define serialization mappings
|
|
5396
5402
|
[example]
|
|
@@ -5439,6 +5445,73 @@ end
|
|
|
5439
5445
|
====
|
|
5440
5446
|
|
|
5441
5447
|
|
|
5448
|
+
[[mapping-rdf]]
|
|
5449
|
+
=== Unified RDF mapping (`rdf`)
|
|
5450
|
+
|
|
5451
|
+
The `rdf` block defines predicate-based mappings once for both JSON-LD and
|
|
5452
|
+
Turtle serialization. It follows the same unified-mapping principle as
|
|
5453
|
+
`key_value` (which serves JSON, YAML, TOML).
|
|
5454
|
+
|
|
5455
|
+
.Using the `rdf` block to define unified RDF mappings
|
|
5456
|
+
[example]
|
|
5457
|
+
====
|
|
5458
|
+
[source,ruby]
|
|
5459
|
+
----
|
|
5460
|
+
class Concept < Lutaml::Model::Serializable
|
|
5461
|
+
attribute :code, :string
|
|
5462
|
+
attribute :name, :string
|
|
5463
|
+
|
|
5464
|
+
rdf do
|
|
5465
|
+
namespace SkosNamespace
|
|
5466
|
+
|
|
5467
|
+
subject { |m| "http://example.org/concept/#{m.code}" }
|
|
5468
|
+
type "skos:Concept"
|
|
5469
|
+
|
|
5470
|
+
predicate :notation, namespace: SkosNamespace, to: :code
|
|
5471
|
+
predicate :prefLabel, namespace: SkosNamespace, to: :name
|
|
5472
|
+
end
|
|
5473
|
+
end
|
|
5474
|
+
----
|
|
5475
|
+
|
|
5476
|
+
Serializes to both formats:
|
|
5477
|
+
|
|
5478
|
+
[source,ruby]
|
|
5479
|
+
----
|
|
5480
|
+
concept = Concept.new(code: "2119", name: "component")
|
|
5481
|
+
concept.to_turtle # => Turtle with @prefix, a skos:Concept, predicates
|
|
5482
|
+
concept.to_jsonld # => JSON-LD with @context, @type, @id, properties
|
|
5483
|
+
----
|
|
5484
|
+
====
|
|
5485
|
+
|
|
5486
|
+
Graph-level serialization uses `members` to emit all contained resources as
|
|
5487
|
+
separate subjects in the same document:
|
|
5488
|
+
|
|
5489
|
+
[source,ruby]
|
|
5490
|
+
----
|
|
5491
|
+
class Vocabulary < Lutaml::Model::Serializable
|
|
5492
|
+
attribute :id, :string
|
|
5493
|
+
attribute :concepts, Concept, collection: true
|
|
5494
|
+
|
|
5495
|
+
rdf do
|
|
5496
|
+
namespace SkosNamespace
|
|
5497
|
+
subject { |v| "http://example.org/vocab/#{v.id}" }
|
|
5498
|
+
type "skos:ConceptScheme"
|
|
5499
|
+
predicate :prefLabel, namespace: SkosNamespace, to: :id
|
|
5500
|
+
members :concepts
|
|
5501
|
+
end
|
|
5502
|
+
end
|
|
5503
|
+
|
|
5504
|
+
# Turtle: single document with ConceptScheme + all Concept triples
|
|
5505
|
+
# JSON-LD: @graph array with ConceptScheme + all Concept objects
|
|
5506
|
+
vocab.to_turtle
|
|
5507
|
+
vocab.to_jsonld
|
|
5508
|
+
----
|
|
5509
|
+
|
|
5510
|
+
See link:docs/_guides/rdf-serialization.adoc[Unified RDF Serialization] for the
|
|
5511
|
+
complete guide including language-tagged values, graph serialization, and
|
|
5512
|
+
architecture details.
|
|
5513
|
+
|
|
5514
|
+
|
|
5442
5515
|
== Serialization: XML
|
|
5443
5516
|
|
|
5444
5517
|
=== General
|
|
@@ -10100,8 +10173,14 @@ Key-value data models supported are identified by their short name:
|
|
|
10100
10173
|
`json`:: JSON
|
|
10101
10174
|
`yaml`:: YAML
|
|
10102
10175
|
`toml`:: TOML
|
|
10176
|
+
`jsonld`:: JSON-LD (extends key-value with `@context`, `@type`, `@id`)
|
|
10103
10177
|
`key_value`:: A way to configure key-value mappings for all supported key-value data models.
|
|
10104
10178
|
|
|
10179
|
+
RDF serialization formats::
|
|
10180
|
+
|
|
10181
|
+
`rdf`:: Unified RDF mapping for both JSON-LD and Turtle (see <<mapping-rdf>>)
|
|
10182
|
+
`turtle`:: Turtle (see link:docs/_guides/turtle-serialization.adoc[Turtle Serialization])
|
|
10183
|
+
|
|
10105
10184
|
|
|
10106
10185
|
=== Mapping
|
|
10107
10186
|
|
|
@@ -15735,6 +15814,8 @@ LutaML, out of the box, supports the following serialization formats:
|
|
|
15735
15814
|
* YAML (https://yaml.org/[YAML version 1.2])
|
|
15736
15815
|
* JSON (https://www.ecma-international.org/publications-and-standards/standards/ecma-404/[ECMA-404 The JSON Data Interchange Standard], unofficial link: https://www.json.org[JSON])
|
|
15737
15816
|
* TOML (https://toml.io/en[TOML version 1.0])
|
|
15817
|
+
* JSON-LD (https://www.w3.org/TR/json-ld11/[W3C JSON-LD 1.1])
|
|
15818
|
+
* Turtle (https://www.w3.org/TR/turtle/[W3C RDF 1.1 Turtle])
|
|
15738
15819
|
|
|
15739
15820
|
The adapter interface is also used to support certain transformation of models
|
|
15740
15821
|
into an "end format", which is not a serialization format. For example, the
|
|
@@ -15977,6 +16058,37 @@ end
|
|
|
15977
16058
|
----
|
|
15978
16059
|
|
|
15979
16060
|
|
|
16061
|
+
=== JSON-LD
|
|
16062
|
+
|
|
16063
|
+
Lutaml::Model supports serialization to and from JSON-LD (W3C JSON-LD 1.1).
|
|
16064
|
+
JSON-LD is a key-value format that extends JSON with `@context`, `@type`, and
|
|
16065
|
+
`@id`. No additional gem is required beyond `lutaml-model`.
|
|
16066
|
+
|
|
16067
|
+
For unified RDF mapping (both JSON-LD and Turtle from a single `rdf` block), see
|
|
16068
|
+
link:docs/_guides/rdf-serialization.adoc[Unified RDF Serialization].
|
|
16069
|
+
|
|
16070
|
+
See link:docs/_guides/jsonld-serialization.adoc[JSON-LD Serialization] for the
|
|
16071
|
+
legacy `jsonld do` block DSL and usage examples.
|
|
16072
|
+
|
|
16073
|
+
|
|
16074
|
+
=== Turtle
|
|
16075
|
+
|
|
16076
|
+
Lutaml::Model supports serialization to and from W3C RDF Turtle format.
|
|
16077
|
+
Turtle is a non-key-value format based on RDF triples. Requires the
|
|
16078
|
+
`rdf-turtle` gem:
|
|
16079
|
+
|
|
16080
|
+
[source,ruby]
|
|
16081
|
+
----
|
|
16082
|
+
gem "rdf-turtle", "~> 3.3"
|
|
16083
|
+
----
|
|
16084
|
+
|
|
16085
|
+
For unified RDF mapping (both JSON-LD and Turtle from a single `rdf` block), see
|
|
16086
|
+
link:docs/_guides/rdf-serialization.adoc[Unified RDF Serialization].
|
|
16087
|
+
|
|
16088
|
+
See link:docs/_guides/turtle-serialization.adoc[Turtle Serialization] for the
|
|
16089
|
+
legacy `turtle do` block DSL and usage examples.
|
|
16090
|
+
|
|
16091
|
+
|
|
15980
16092
|
=== Per-operation adapter override
|
|
15981
16093
|
|
|
15982
16094
|
Override the adapter for a single serialization/deserialization call using the `adapter:` option:
|
data/docs/_guides/index.adoc
CHANGED
|
@@ -22,6 +22,17 @@ Task-oriented guides for accomplishing specific goals with Lutaml::Model.
|
|
|
22
22
|
* link:../keyvalue-serialization[Key-Value Serialization] - JSON/YAML/TOML/Hash
|
|
23
23
|
* link:../collection-serialization[Collection Serialization] - JSONL and YAML Stream
|
|
24
24
|
|
|
25
|
+
== Linked Data serialization
|
|
26
|
+
|
|
27
|
+
* link:../rdf-serialization[Unified RDF Serialization] - One `rdf` block for both JSON-LD and Turtle
|
|
28
|
+
* link:../jsonld-serialization[JSON-LD Serialization] - W3C JSON-LD 1.1 with `@context`
|
|
29
|
+
* link:../turtle-serialization[Turtle Serialization] - W3C RDF Turtle format
|
|
30
|
+
|
|
31
|
+
== RDF infrastructure
|
|
32
|
+
|
|
33
|
+
See link:../references/rdf-namespaces[RDF Namespaces] for namespace classes,
|
|
34
|
+
`NamespaceSet`, `Iri`, and `Literal` value objects.
|
|
35
|
+
|
|
25
36
|
== Advanced features
|
|
26
37
|
|
|
27
38
|
* link:../value-transformations[Value Transformations] - Transform values during serialization
|
|
@@ -49,6 +60,13 @@ Task-oriented guides for accomplishing specific goals with Lutaml::Model.
|
|
|
49
60
|
. link:../value-transformations[Transform values if needed]
|
|
50
61
|
. link:../missing-values-handling[Handle nil/empty values]
|
|
51
62
|
|
|
63
|
+
=== I want to serialize to JSON-LD or Turtle (Linked Data)
|
|
64
|
+
|
|
65
|
+
. link:../rdf-serialization[Unified RDF Serialization] (recommended — one block for both formats)
|
|
66
|
+
. link:../jsonld-serialization[JSON-LD Serialization guide] (legacy `jsonld do` block)
|
|
67
|
+
. link:../turtle-serialization[Turtle Serialization guide] (legacy `turtle do` block)
|
|
68
|
+
. link:../references/rdf-namespaces[RDF Namespaces reference]
|
|
69
|
+
|
|
52
70
|
=== I want to work with collections
|
|
53
71
|
|
|
54
72
|
. link:../collection-serialization[Collection Serialization]
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: JSON-LD Serialization
|
|
3
|
+
nav_order: 15
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
= JSON-LD Serialization
|
|
7
|
+
|
|
8
|
+
Lutaml::Model supports serialization to and from JSON-LD (W3C JSON-LD 1.1) using
|
|
9
|
+
SKOS, Dublin Core Terms, and other W3C vocabularies.
|
|
10
|
+
|
|
11
|
+
== Setup
|
|
12
|
+
|
|
13
|
+
JSON-LD is built on the key-value serialization pipeline and requires no
|
|
14
|
+
additional gems beyond what JSON already uses. The `json-ld` gem may be added
|
|
15
|
+
for advanced JSON-LD Processing (expansion, compaction, flattening) in the
|
|
16
|
+
future.
|
|
17
|
+
|
|
18
|
+
JSON-LD is a **key-value** format adapter that extends the built-in key-value
|
|
19
|
+
serialization with JSON-LD-specific constructs: `@context`, `@type`, and
|
|
20
|
+
`@id`.
|
|
21
|
+
|
|
22
|
+
== Mapping DSL
|
|
23
|
+
|
|
24
|
+
Use the `jsonld do` block in your model to define JSON-LD mappings:
|
|
25
|
+
|
|
26
|
+
[source,ruby]
|
|
27
|
+
----
|
|
28
|
+
class Concept < Lutaml::Model::Serializable
|
|
29
|
+
attribute :name, :string
|
|
30
|
+
attribute :description, :string
|
|
31
|
+
|
|
32
|
+
jsonld do
|
|
33
|
+
context do
|
|
34
|
+
prefix Lutaml::Rdf::Namespaces::SkosNamespace
|
|
35
|
+
vocab "http://example.org/ns/"
|
|
36
|
+
|
|
37
|
+
term "name", id: "http://example.org/name"
|
|
38
|
+
term "description", id: "http://example.org/description"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
type "skos:Concept"
|
|
42
|
+
id { |m| "http://example.org/concept/#{m.name}" }
|
|
43
|
+
|
|
44
|
+
map "name", to: :name
|
|
45
|
+
map "description", to: :description
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
----
|
|
49
|
+
|
|
50
|
+
=== Context
|
|
51
|
+
|
|
52
|
+
The `context` block builds the `@context` object in the JSON-LD output:
|
|
53
|
+
|
|
54
|
+
* `prefix(NamespaceClass)` — registers an RDF namespace as a prefix
|
|
55
|
+
* `vocab(uri)` — sets `@vocab` for unprefixed terms
|
|
56
|
+
* `language(code)` — sets default `@language`
|
|
57
|
+
* `base(uri)` — sets `@base` URI
|
|
58
|
+
* `term(name, ...)` — defines a term with optional `id:`, `type:`,
|
|
59
|
+
`container:`, `language:`, `reverse:`
|
|
60
|
+
|
|
61
|
+
Context resolution:
|
|
62
|
+
|
|
63
|
+
* Compact IRIs (e.g., `"skos:Concept"`) are expanded to full URIs via prefix
|
|
64
|
+
* Terms are resolved via the term definitions
|
|
65
|
+
* Unprefixed names are resolved via `@vocab`
|
|
66
|
+
|
|
67
|
+
=== Type and ID
|
|
68
|
+
|
|
69
|
+
* `type "skos:Concept"` — sets `@type` in the output (resolved to full IRI via
|
|
70
|
+
context)
|
|
71
|
+
* `id { |model| ... }` — generates `@id` from the model instance
|
|
72
|
+
|
|
73
|
+
Both are optional. Omit `type` or `id` if your JSON-LD document does not
|
|
74
|
+
require them.
|
|
75
|
+
|
|
76
|
+
=== map
|
|
77
|
+
|
|
78
|
+
`map` entries work identically to key-value serialization, defining the JSON
|
|
79
|
+
properties serialized from model attributes.
|
|
80
|
+
|
|
81
|
+
== Serialization
|
|
82
|
+
|
|
83
|
+
[source,ruby]
|
|
84
|
+
----
|
|
85
|
+
concept = Concept.new(name: "test", description: "A test concept")
|
|
86
|
+
jsonld = concept.to_jsonld
|
|
87
|
+
----
|
|
88
|
+
|
|
89
|
+
Produces:
|
|
90
|
+
|
|
91
|
+
[source,json]
|
|
92
|
+
----
|
|
93
|
+
{
|
|
94
|
+
"@context": {
|
|
95
|
+
"skos": "http://www.w3.org/2004/02/skos/core#",
|
|
96
|
+
"@vocab": "http://example.org/ns/",
|
|
97
|
+
"name": "http://example.org/name",
|
|
98
|
+
"description": "http://example.org/description"
|
|
99
|
+
},
|
|
100
|
+
"@type": "http://www.w3.org/2004/02/skos/core#Concept",
|
|
101
|
+
"@id": "http://example.org/concept/test",
|
|
102
|
+
"name": "test",
|
|
103
|
+
"description": "A test concept"
|
|
104
|
+
}
|
|
105
|
+
----
|
|
106
|
+
|
|
107
|
+
Nil attribute values are omitted from the output.
|
|
108
|
+
|
|
109
|
+
== Deserialization
|
|
110
|
+
|
|
111
|
+
[source,ruby]
|
|
112
|
+
----
|
|
113
|
+
concept = Concept.from_jsonld(jsonld_string)
|
|
114
|
+
puts concept.name # => "test"
|
|
115
|
+
----
|
|
116
|
+
|
|
117
|
+
The `from_jsonld` method:
|
|
118
|
+
|
|
119
|
+
. Parses the JSON-LD string into a hash via `JSON.parse`
|
|
120
|
+
. Strips all `@`-prefixed keywords (`@context`, `@type`, `@id`, `@graph`,
|
|
121
|
+
etc.) before attribute mapping
|
|
122
|
+
. Delegates attribute mapping to the key-value transform pipeline
|
|
123
|
+
|
|
124
|
+
This prevents JSON-LD keywords from colliding with model attributes named
|
|
125
|
+
`type`, `id`, `context`, etc.
|
|
126
|
+
|
|
127
|
+
== Round-trip
|
|
128
|
+
|
|
129
|
+
Model data round-trips through JSON-LD serialization:
|
|
130
|
+
|
|
131
|
+
[source,ruby]
|
|
132
|
+
----
|
|
133
|
+
restored = Concept.from_jsonld(concept.to_jsonld)
|
|
134
|
+
restored.name == concept.name # => true
|
|
135
|
+
----
|
|
136
|
+
|
|
137
|
+
The `@context` structure is preserved across round-trips because it is defined
|
|
138
|
+
in the mapping, not derived from the input.
|
|
139
|
+
|
|
140
|
+
== Unified `rdf` DSL
|
|
141
|
+
|
|
142
|
+
If you need both JSON-LD and Turtle output from the same model, use the
|
|
143
|
+
unified `rdf` DSL instead of separate `jsonld` and `turtle` blocks. This
|
|
144
|
+
defines the mapping once and auto-generates `@context` from predicates:
|
|
145
|
+
|
|
146
|
+
[source,ruby]
|
|
147
|
+
----
|
|
148
|
+
class Concept < Lutaml::Model::Serializable
|
|
149
|
+
attribute :name, :string
|
|
150
|
+
attribute :code, :string
|
|
151
|
+
|
|
152
|
+
rdf do
|
|
153
|
+
namespace Lutaml::Rdf::Namespaces::SkosNamespace
|
|
154
|
+
subject { |m| "http://example.org/#{m.code}" }
|
|
155
|
+
type "skos:Concept"
|
|
156
|
+
predicate :prefLabel, namespace: SkosNamespace, to: :name
|
|
157
|
+
predicate :notation, namespace: SkosNamespace, to: :code
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
----
|
|
161
|
+
|
|
162
|
+
See link:../_guides/rdf-serialization.adoc[Unified RDF Serialization] for the
|
|
163
|
+
complete guide including graph-level serialization with `members`.
|
|
164
|
+
|
|
165
|
+
== Multi-format models
|
|
166
|
+
|
|
167
|
+
A single model can define `json`, `jsonld`, `turtle`, and `rdf` mappings
|
|
168
|
+
simultaneously. Each format operates independently:
|
|
169
|
+
|
|
170
|
+
[source,ruby]
|
|
171
|
+
----
|
|
172
|
+
class Concept < Lutaml::Model::Serializable
|
|
173
|
+
attribute :name, :string
|
|
174
|
+
attribute :code, :string
|
|
175
|
+
|
|
176
|
+
json do
|
|
177
|
+
map "name", to: :name
|
|
178
|
+
map "code", to: :code
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
rdf do
|
|
182
|
+
namespace Lutaml::Rdf::Namespaces::SkosNamespace
|
|
183
|
+
subject { |m| "http://example.org/#{m.code}" }
|
|
184
|
+
type "skos:Concept"
|
|
185
|
+
predicate :prefLabel, namespace: SkosNamespace, to: :name
|
|
186
|
+
predicate :notation, namespace: SkosNamespace, to: :code
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
----
|
|
190
|
+
|
|
191
|
+
* `to_json` produces plain JSON without `@context`
|
|
192
|
+
* `to_jsonld` produces JSON-LD with auto-generated `@context`, `@type`, `@id`
|
|
193
|
+
* `to_turtle` produces Turtle with `@prefix` declarations
|
|
194
|
+
|
|
195
|
+
The unified `rdf` block creates mappings for both `:turtle` and `:jsonld`
|
|
196
|
+
formats. If separate `jsonld do` or `turtle do` blocks are also defined, they
|
|
197
|
+
take precedence over the `rdf` block for their respective format.
|
|
198
|
+
|
|
199
|
+
== Error Handling
|
|
200
|
+
|
|
201
|
+
* `JSON::ParserError` — raised for malformed JSON input
|
|
202
|
+
* All parsing errors are wrapped in `Lutaml::Model::InvalidFormatError` by the
|
|
203
|
+
format pipeline
|
|
204
|
+
|
|
205
|
+
== Architecture
|
|
206
|
+
|
|
207
|
+
The JSON-LD format is composed of:
|
|
208
|
+
|
|
209
|
+
* `Lutaml::JsonLd::Adapter` — extends `KeyValue::Document`; parses JSON-LD
|
|
210
|
+
strings to hashes and serializes hashes back to JSON
|
|
211
|
+
* `Lutaml::JsonLd::Context` — DSL for building `@context` with prefixes,
|
|
212
|
+
vocab, terms, language, and base
|
|
213
|
+
* `Lutaml::JsonLd::TermDefinition` — value object for term definitions with
|
|
214
|
+
`@id`, `@type`, `@container`, `@language`, `@reverse`
|
|
215
|
+
* `Lutaml::JsonLd::Transform` — inherits from `Rdf::Transform`; auto-generates
|
|
216
|
+
`@context` from predicates, injects `@type`/`@id` on export, strips
|
|
217
|
+
`@`-keywords on import
|