json-ld 3.1.2 → 3.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +124 -48
- data/VERSION +1 -1
- data/bin/jsonld +27 -30
- data/lib/json/ld.rb +6 -2
- data/lib/json/ld/api.rb +33 -24
- data/lib/json/ld/compact.rb +65 -37
- data/lib/json/ld/conneg.rb +1 -1
- data/lib/json/ld/context.rb +612 -539
- data/lib/json/ld/expand.rb +158 -77
- data/lib/json/ld/format.rb +20 -7
- data/lib/json/ld/from_rdf.rb +40 -17
- data/lib/json/ld/reader.rb +20 -11
- data/lib/json/ld/streaming_reader.rb +578 -0
- data/lib/json/ld/to_rdf.rb +9 -5
- data/lib/json/ld/writer.rb +10 -3
- data/spec/compact_spec.rb +207 -2
- data/spec/context_spec.rb +13 -60
- data/spec/expand_spec.rb +248 -0
- data/spec/from_rdf_spec.rb +181 -0
- data/spec/matchers.rb +1 -1
- data/spec/reader_spec.rb +33 -34
- data/spec/streaming_reader_spec.rb +237 -0
- data/spec/suite_helper.rb +14 -8
- data/spec/suite_to_rdf_spec.rb +1 -0
- data/spec/to_rdf_spec.rb +206 -0
- data/spec/writer_spec.rb +193 -0
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9345f0853c9ee6d7e1bb91817ca7d9effc1ce5d591f98fa92a11c396c1f0fbb
|
4
|
+
data.tar.gz: 7a84d8f7b4dd0fe379dd8b915d6e899f610807959d9ea4ef66c0ab4c22657807
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2ff1429edeea61f1655e445862140b5477dfa978cfaeaa3a417417fff24adfc17b6adea77cb24041c8c3daafaf7661d05023a3f1e2e4c161194be7dc4c96dd7
|
7
|
+
data.tar.gz: e04b64a78d9bfdc88d808219440b758540a3e6bd2f7dae4ee73831b093ab8ada77641acfc2c4c079b413f17b0d88a0149058fa3959c2fbdd6e0d421c8885fa5a
|
data/README.md
CHANGED
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
[JSON-LD][] reader/writer for [RDF.rb][RDF.rb] and fully conforming [JSON-LD API][] processor. Additionally this gem implements [JSON-LD Framing][].
|
4
4
|
|
5
|
-
[![Gem Version](https://badge.fury.io/rb/json-ld.png)](https://
|
6
|
-
[![Build Status](https://secure.travis-ci.org/ruby-rdf/json-ld.png?branch=
|
7
|
-
[![Coverage Status](https://coveralls.io/repos/ruby-rdf/json-ld/badge.svg)](https://coveralls.io/
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/json-ld.png)](https://rubygems.org/gems/json-ld)
|
6
|
+
[![Build Status](https://secure.travis-ci.org/ruby-rdf/json-ld.png?branch=develop)](https://github.com/ruby-rdf/json-ld/actions?query=workflow%3ACI)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/ruby-rdf/json-ld/badge.svg)](https://coveralls.io/github/ruby-rdf/json-ld)
|
8
|
+
[![Gitter chat](https://badges.gitter.im/ruby-rdf.png)](https://gitter.im/gitterHQ/gitter)
|
8
9
|
|
9
10
|
## Features
|
10
11
|
|
@@ -14,26 +15,90 @@ JSON::LD can now be used to create a _context_ from an RDFS/OWL definition, and
|
|
14
15
|
|
15
16
|
* If the [jsonlint][] gem is installed, it will be used when validating an input document.
|
16
17
|
* If available, uses [Nokogiri][] and/or [Nokogumbo][] for parsing HTML, falls back to REXML otherwise.
|
18
|
+
* Provisional support for [JSON-LD*][JSON-LD*].
|
17
19
|
|
18
20
|
[Implementation Report](file.earl.html)
|
19
21
|
|
20
22
|
Install with `gem install json-ld`
|
21
23
|
|
24
|
+
### JSON-LD Streaming Profile
|
25
|
+
This gem implements an optimized streaming reader used for generating RDF from large dataset dumps formatted as JSON-LD. Such documents must correspond to the [JSON-LD Streaming Profile](https://w3c.github.io/json-ld-streaming/):
|
26
|
+
|
27
|
+
* Keys in JSON objects must be ordered with any of `@context`, and/or `@type` coming before any other keys, in that order. This includes aliases of those keys. It is strongly encouraged that `@id` be present, and come immediately after.
|
28
|
+
* JSON-LD documents can be signaled or requested in [streaming document form](https://w3c.github.io/json-ld-streaming/#dfn-streaming-document-form). The profile URI identifying the [streaming document form](https://w3c.github.io/json-ld-streaming/#dfn-streaming-document-form) is `http://www.w3.org/ns/json-ld#streaming`.
|
29
|
+
|
30
|
+
This gem also implements an optimized streaming writer used for generating JSON-LD from large repositories. Such documents result in the JSON-LD Streaming Profile:
|
31
|
+
|
32
|
+
* Each statement written as a separate node in expanded/flattened form.
|
33
|
+
* `RDF List`s are written as separate nodes using `rdf:first` and `rdf:rest` properties.
|
34
|
+
|
35
|
+
The order of triples retrieved from the `RDF::Enumerable` dataset determines the way that JSON-LD node objects are written; for best results, statements should be ordered by _graph name_, _subect_, _predicate_ and _object_.
|
36
|
+
|
22
37
|
### MultiJson parser
|
23
38
|
The [MultiJson](https://rubygems.org/gems/multi_json) gem is used for parsing JSON; this defaults to the native JSON parser, but will use a more performant parser if one is available. A specific parser can be specified by adding the `:adapter` option to any API call. See [MultiJson](https://rubygems.org/gems/multi_json) for more information.
|
24
39
|
|
25
|
-
### JSON-LD
|
26
|
-
This gem implements an optimized streaming writer used for generating JSON-LD from large repositories. Such documents result in the JSON-LD Streaming Profile:
|
40
|
+
### JSON-LD* (RDFStar)
|
27
41
|
|
28
|
-
|
29
|
-
|
42
|
+
The {JSON::LD::API.toRdf} and {JSON::LD::API.fromRdf} API methods, along with the {JSON::LD::Reader} and {JSON::LD::Writer}, include provisional support for [JSON-LD*][JSON-LD*].
|
43
|
+
|
44
|
+
Internally, an `RDF::Statement` is treated as another resource, along with `RDF::URI` and `RDF::Node`, which allows an `RDF::Statement` to have a `#subject` or `#object` which is also an `RDF::Statement`.
|
45
|
+
|
46
|
+
In JSON-LD, with the `rdfstar` option set, the value of `@id`, in addition to an IRI or Blank Node Identifier, can be a JSON-LD node object having exactly one property with an optional `@id`, which may also be an embedded object. (It may also have `@context` and `@index` values).
|
47
|
+
|
48
|
+
{
|
49
|
+
"@id": {
|
50
|
+
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
51
|
+
"@index": "ignored",
|
52
|
+
"@id": "bob",
|
53
|
+
"foaf:age" 23
|
54
|
+
},
|
55
|
+
"ex:certainty": 0.9
|
56
|
+
}
|
57
|
+
|
58
|
+
**Note: This feature is subject to change or elimination as the standards process progresses.**
|
59
|
+
|
60
|
+
#### Serializing a Graph containing embedded statements
|
61
|
+
|
62
|
+
require 'json-ld'
|
63
|
+
statement = RDF::Statement(RDF::URI('bob'), RDF::Vocab::FOAF.age, RDF::Literal(23))
|
64
|
+
graph = RDF::Graph.new << [statement, RDF::URI("ex:certainty"), RDF::Literal(0.9)]
|
65
|
+
graph.dump(:jsonld, validate: false, standard_prefixes: true)
|
66
|
+
# => {"@id": {"@id": "bob", "foaf:age" 23}, "ex:certainty": 0.9}
|
67
|
+
|
68
|
+
Alternatively, using the {JSON::LD::API.fromRdf} method:
|
69
|
+
|
70
|
+
JSON::LD::API::fromRdf(graph)
|
71
|
+
# => {"@id": {"@id": "bob", "foaf:age" 23}, "ex:certainty": 0.9}
|
72
|
+
|
73
|
+
#### Reading a Graph containing embedded statements
|
74
|
+
|
75
|
+
By default, {JSON::LD::API.toRdf} (and {JSON::LD::Reader}) will reject a document containing a subject resource.
|
76
|
+
|
77
|
+
jsonld = %({
|
78
|
+
"@id": {
|
79
|
+
"@id": "bob", "foaf:age" 23
|
80
|
+
},
|
81
|
+
"ex:certainty": 0.9
|
82
|
+
})
|
83
|
+
graph = RDF::Graph.new << JSON::LD::API.toRdf(input)
|
84
|
+
# => JSON::LD::JsonLdError::InvalidIdValue
|
85
|
+
|
86
|
+
{JSON::LD::API.toRdf} (and {JSON::LD::Reader}) support a boolean valued `rdfstar` option; only one statement is asserted, although the reified statement is contained within the graph.
|
87
|
+
|
88
|
+
graph = RDF::Graph.new do |graph|
|
89
|
+
JSON::LD::Reader.new(jsonld, rdfstar: true) {|reader| graph << reader}
|
90
|
+
end
|
91
|
+
graph.count #=> 1
|
30
92
|
|
31
93
|
## Examples
|
94
|
+
|
32
95
|
```ruby
|
33
96
|
require 'rubygems'
|
34
97
|
require 'json/ld'
|
35
98
|
```
|
99
|
+
|
36
100
|
### Expand a Document
|
101
|
+
|
37
102
|
```ruby
|
38
103
|
input = JSON.parse %({
|
39
104
|
"@context": {
|
@@ -53,8 +118,9 @@ require 'json/ld'
|
|
53
118
|
"http://xmlns.com/foaf/0.1/avatar": [{"@value": "https://twitter.com/account/profile_image/manusporny"}]
|
54
119
|
}]
|
55
120
|
```
|
121
|
+
|
56
122
|
### Compact a Document
|
57
|
-
|
123
|
+
|
58
124
|
input = JSON.parse %([{
|
59
125
|
"http://xmlns.com/foaf/0.1/name": ["Manu Sporny"],
|
60
126
|
"http://xmlns.com/foaf/0.1/homepage": [{"@id": "https://manu.sporny.org/"}],
|
@@ -80,9 +146,9 @@ require 'json/ld'
|
|
80
146
|
"homepage": "https://manu.sporny.org/",
|
81
147
|
"name": "Manu Sporny"
|
82
148
|
}
|
83
|
-
|
149
|
+
|
84
150
|
### Frame a Document
|
85
|
-
|
151
|
+
|
86
152
|
input = JSON.parse %({
|
87
153
|
"@context": {
|
88
154
|
"Book": "http://example.org/vocab#Book",
|
@@ -163,9 +229,9 @@ require 'json/ld'
|
|
163
229
|
}
|
164
230
|
]
|
165
231
|
}
|
166
|
-
|
232
|
+
|
167
233
|
### Turn JSON-LD into RDF (Turtle)
|
168
|
-
|
234
|
+
|
169
235
|
input = JSON.parse %({
|
170
236
|
"@context": {
|
171
237
|
"": "https://manu.sporny.org/",
|
@@ -186,9 +252,9 @@ require 'json/ld'
|
|
186
252
|
<http://example.org/people#joebob> a foaf:Person;
|
187
253
|
foaf:name "Joe Bob";
|
188
254
|
foaf:nick ("joe" "bob" "jaybe") .
|
189
|
-
|
255
|
+
|
190
256
|
### Turn RDF into JSON-LD
|
191
|
-
|
257
|
+
|
192
258
|
require 'rdf/turtle'
|
193
259
|
input = RDF::Graph.new << RDF::Turtle::Reader.new(%(
|
194
260
|
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
|
@@ -224,13 +290,14 @@ require 'json/ld'
|
|
224
290
|
"http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}]
|
225
291
|
}
|
226
292
|
]
|
227
|
-
|
293
|
+
|
228
294
|
## Use a custom Document Loader
|
229
295
|
In some cases, the built-in document loader {JSON::LD::API.documentLoader} is inadequate; for example, when using `http://schema.org` as a remote context, it will be re-loaded every time (however, see [json-ld-preloaded](https://rubygems.org/gems/json-ld-preloaded)).
|
230
296
|
|
231
297
|
All entries into the {JSON::LD::API} accept a `:documentLoader` option, which can be used to provide an alternative method to use when loading remote documents. For example:
|
298
|
+
|
232
299
|
```ruby
|
233
|
-
|
300
|
+
load_document_local = Proc.new do |url, **options, &block|
|
234
301
|
if RDF::URI(url, canonicalize: true) == RDF::URI('http://schema.org/')
|
235
302
|
remote_document = JSON::LD::API::RemoteDocument.new(url, File.read("etc/schema.org.jsonld"))
|
236
303
|
return block_given? ? yield(remote_document) : remote_document
|
@@ -238,28 +305,34 @@ def load_document_local(url, options={}, &block)
|
|
238
305
|
JSON::LD::API.documentLoader(url, options, &block)
|
239
306
|
end
|
240
307
|
end
|
308
|
+
|
241
309
|
```
|
242
310
|
Then, when performing something like expansion:
|
311
|
+
|
243
312
|
```ruby
|
244
313
|
JSON::LD::API.expand(input, documentLoader: load_document_local)
|
245
314
|
```
|
246
315
|
|
247
316
|
## Preloading contexts
|
248
317
|
In many cases, for small documents, processing time can be dominated by loading and parsing remote contexts. In particular, a small schema.org example may need to download a large context and turn it into an internal representation, before the actual document can be expanded for processing. Using {JSON::LD::Context.add_preloaded}, an implementation can perform this loading up-front, and make it available to the processor.
|
318
|
+
|
249
319
|
```ruby
|
250
320
|
ctx = JSON::LD::Context.new().parse('http://schema.org/')
|
251
321
|
JSON::LD::Context.add_preloaded('http://schema.org/', ctx)
|
252
322
|
```
|
323
|
+
|
253
324
|
On lookup, URIs with an `https` prefix are normalized to `http`.
|
254
325
|
|
255
326
|
A context may be serialized to Ruby to speed this process using `Context#to_rb`. When loaded, this generated file will add entries to the {JSON::LD::Context::PRELOADED}.
|
256
327
|
|
257
328
|
## RDF Reader and Writer
|
258
329
|
{JSON::LD} also acts as a normal RDF reader and writer, using the standard RDF.rb reader/writer interfaces:
|
330
|
+
|
259
331
|
```ruby
|
260
332
|
graph = RDF::Graph.load("etc/doap.jsonld", format: :jsonld)
|
261
333
|
graph.dump(:jsonld, standard_prefixes: true)
|
262
334
|
```
|
335
|
+
|
263
336
|
`RDF::GRAPH#dump` can also take a `:context` option to use a separately defined context
|
264
337
|
|
265
338
|
As JSON-LD may come from many different sources, included as an embedded script tag within an HTML document, the RDF Reader will strip input before the leading `{` or `[` and after the trailing `}` or `]`.
|
@@ -269,7 +342,7 @@ This implementation is being used as a test-bed for features planned for an upco
|
|
269
342
|
|
270
343
|
### Scoped Contexts
|
271
344
|
A term definition can include `@context`, which is applied to values of that object. This is also used when compacting. Taken together, this allows framing to effectively include context definitions more deeply within the framed structure.
|
272
|
-
|
345
|
+
|
273
346
|
{
|
274
347
|
"@context": {
|
275
348
|
"ex": "http://example.com/",
|
@@ -284,10 +357,10 @@ A term definition can include `@context`, which is applied to values of that obj
|
|
284
357
|
},
|
285
358
|
"foo": "Bar"
|
286
359
|
}
|
287
|
-
|
360
|
+
|
288
361
|
### @id and @type maps
|
289
362
|
The value of `@container` in a term definition can include `@id` or `@type`, in addition to `@set`, `@list`, `@language`, and `@index`. This allows value indexing based on either the `@id` or `@type` of associated objects.
|
290
|
-
|
363
|
+
|
291
364
|
{
|
292
365
|
"@context": {
|
293
366
|
"@vocab": "http://example/",
|
@@ -298,10 +371,10 @@ The value of `@container` in a term definition can include `@id` or `@type`, in
|
|
298
371
|
"_:bar": {"label": "Object with @id _:bar"}
|
299
372
|
}
|
300
373
|
}
|
301
|
-
|
374
|
+
|
302
375
|
### @graph containers and maps
|
303
376
|
A term can have `@container` set to include `@graph` optionally including `@id` or `@index` and `@set`. In the first form, with `@container` set to `@graph`, the value of a property is treated as a _simple graph object_, meaning that values treated as if they were contained in an object with `@graph`, creating _named graph_ with an anonymous name.
|
304
|
-
|
377
|
+
|
305
378
|
{
|
306
379
|
"@context": {
|
307
380
|
"@vocab": "http://example.org/",
|
@@ -311,9 +384,9 @@ A term can have `@container` set to include `@graph` optionally including `@id`
|
|
311
384
|
"value": "x"
|
312
385
|
}
|
313
386
|
}
|
314
|
-
|
387
|
+
|
315
388
|
which expands to the following:
|
316
|
-
|
389
|
+
|
317
390
|
[{
|
318
391
|
"http://example.org/input": [{
|
319
392
|
"@graph": [{
|
@@ -321,18 +394,18 @@ which expands to the following:
|
|
321
394
|
}]
|
322
395
|
}]
|
323
396
|
}]
|
324
|
-
|
397
|
+
|
325
398
|
Compaction reverses this process, optionally ensuring that a single value is contained within an array of `@container` also includes `@set`:
|
326
|
-
|
399
|
+
|
327
400
|
{
|
328
401
|
"@context": {
|
329
402
|
"@vocab": "http://example.org/",
|
330
403
|
"input": {"@container": ["@graph", "@set"]}
|
331
404
|
}
|
332
405
|
}
|
333
|
-
|
406
|
+
|
334
407
|
A graph map uses the map form already existing for `@index`, `@language`, `@type`, and `@id` where the index is either an index value or an id.
|
335
|
-
|
408
|
+
|
336
409
|
{
|
337
410
|
"@context": {
|
338
411
|
"@vocab": "http://example.org/",
|
@@ -342,9 +415,9 @@ A graph map uses the map form already existing for `@index`, `@language`, `@type
|
|
342
415
|
"g1": {"value": "x"}
|
343
416
|
}
|
344
417
|
}
|
345
|
-
|
418
|
+
|
346
419
|
treats "g1" as an index, and expands to the following:
|
347
|
-
|
420
|
+
|
348
421
|
[{
|
349
422
|
"http://example.org/input": [{
|
350
423
|
"@index": "g1",
|
@@ -353,11 +426,11 @@ treats "g1" as an index, and expands to the following:
|
|
353
426
|
}]
|
354
427
|
}]
|
355
428
|
}])
|
356
|
-
|
429
|
+
|
357
430
|
This can also include `@set` to ensure that, when compacting, a single value of an index will be in array form.
|
358
431
|
|
359
432
|
The _id_ version is similar:
|
360
|
-
|
433
|
+
|
361
434
|
{
|
362
435
|
"@context": {
|
363
436
|
"@vocab": "http://example.org/",
|
@@ -367,9 +440,9 @@ The _id_ version is similar:
|
|
367
440
|
"http://example.com/g1": {"value": "x"}
|
368
441
|
}
|
369
442
|
}
|
370
|
-
|
443
|
+
|
371
444
|
which expands to:
|
372
|
-
|
445
|
+
|
373
446
|
[{
|
374
447
|
"http://example.org/input": [{
|
375
448
|
"@id": "http://example.com/g1",
|
@@ -378,10 +451,10 @@ which expands to:
|
|
378
451
|
}]
|
379
452
|
}]
|
380
453
|
}])
|
381
|
-
|
454
|
+
|
382
455
|
### Transparent Nesting
|
383
456
|
Many JSON APIs separate properties from their entities using an intermediate object. For example, a set of possible labels may be grouped under a common property:
|
384
|
-
|
457
|
+
|
385
458
|
{
|
386
459
|
"@context": {
|
387
460
|
"skos": "http://www.w3.org/2004/02/skos/core#",
|
@@ -397,9 +470,9 @@ Many JSON APIs separate properties from their entities using an intermediate obj
|
|
397
470
|
"other_label": "This is the other label"
|
398
471
|
}
|
399
472
|
}
|
400
|
-
|
473
|
+
|
401
474
|
In this case, the `labels` property is semantically meaningless. Defining it as equivalent to `@nest` causes it to be ignored when expanding, making it equivalent to the following:
|
402
|
-
|
475
|
+
|
403
476
|
{
|
404
477
|
"@context": {
|
405
478
|
"skos": "http://www.w3.org/2004/02/skos/core#",
|
@@ -413,9 +486,9 @@ Many JSON APIs separate properties from their entities using an intermediate obj
|
|
413
486
|
"main_label": "This is the main label for my resource",
|
414
487
|
"other_label": "This is the other label"
|
415
488
|
}
|
416
|
-
|
489
|
+
|
417
490
|
Similarly, properties may be marked with "@nest": "nest-term", to cause them to be nested. Note that the `@nest` keyword can also be aliased in the context.
|
418
|
-
|
491
|
+
|
419
492
|
{
|
420
493
|
"@context": {
|
421
494
|
"skos": "http://www.w3.org/2004/02/skos/core#",
|
@@ -431,7 +504,7 @@ Many JSON APIs separate properties from their entities using an intermediate obj
|
|
431
504
|
"other_label": "This is the other label"
|
432
505
|
}
|
433
506
|
}
|
434
|
-
|
507
|
+
|
435
508
|
In this way, nesting survives round-tripping through expansion, and framed output can include nested properties.
|
436
509
|
|
437
510
|
## Sinatra/Rack support
|
@@ -509,14 +582,14 @@ Note, the API method signatures differed in versions before 1.0, in that they al
|
|
509
582
|
## Installation
|
510
583
|
The recommended installation method is via [RubyGems](https://rubygems.org/).
|
511
584
|
To install the latest official release of the `JSON-LD` gem, do:
|
512
|
-
|
513
|
-
|
514
|
-
|
585
|
+
|
586
|
+
% [sudo] gem install json-ld
|
587
|
+
|
515
588
|
## Download
|
516
589
|
To get a local working copy of the development repository, do:
|
517
|
-
|
518
|
-
|
519
|
-
|
590
|
+
|
591
|
+
% git clone git://github.com/ruby-rdf/json-ld.git
|
592
|
+
|
520
593
|
## Mailing List
|
521
594
|
* <https://lists.w3.org/Archives/Public/public-rdf-ruby/>
|
522
595
|
|
@@ -534,7 +607,9 @@ To get a local working copy of the development repository, do:
|
|
534
607
|
list in the the `README`. Alphabetical order applies.
|
535
608
|
* Do note that in order for us to merge any non-trivial changes (as a rule
|
536
609
|
of thumb, additions larger than about 15 lines of code), we need an
|
537
|
-
explicit [public domain dedication][PDD] on record from you
|
610
|
+
explicit [public domain dedication][PDD] on record from you,
|
611
|
+
which you will be asked to agree to on the first commit to a repo within the organization.
|
612
|
+
Note that the agreement applies to all repos in the [Ruby RDF](https://github.com/ruby-rdf/) organization.
|
538
613
|
|
539
614
|
License
|
540
615
|
-------
|
@@ -546,8 +621,9 @@ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
|
|
546
621
|
[RDF]: https://www.w3.org/RDF/
|
547
622
|
[YARD]: https://yardoc.org/
|
548
623
|
[YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
|
549
|
-
[PDD]: https://
|
624
|
+
[PDD]: https://unlicense.org/#unlicensing-contributions
|
550
625
|
[RDF.rb]: https://rubygems.org/gems/rdf
|
626
|
+
[JSON-LD*]: https://json-ld.github.io/json-ld-star/
|
551
627
|
[Rack::LinkedData]: https://rubygems.org/gems/rack-linkeddata
|
552
628
|
[Backports]: https://rubygems.org/gems/backports
|
553
629
|
[JSON-LD]: https://www.w3.org/TR/json-ld11/ "JSON-LD 1.1"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.7
|
data/bin/jsonld
CHANGED
@@ -10,7 +10,7 @@ require 'getoptlong'
|
|
10
10
|
require 'open-uri'
|
11
11
|
require 'logger'
|
12
12
|
|
13
|
-
def run(input, options)
|
13
|
+
def run(input, options, parser_options)
|
14
14
|
reader_class = RDF::Reader.for(options[:input_format].to_sym)
|
15
15
|
raise "Reader not found for #{options[:input_format]}" unless reader_class
|
16
16
|
|
@@ -19,38 +19,38 @@ def run(input, options)
|
|
19
19
|
|
20
20
|
# If input format is not JSON-LD, transform input to JSON-LD first
|
21
21
|
reader = if options[:input_format] != :jsonld
|
22
|
-
reader_class.new(input,
|
22
|
+
reader_class.new(input, parser_options)
|
23
23
|
end
|
24
24
|
|
25
25
|
start = Time.new
|
26
26
|
if options[:expand]
|
27
|
-
|
27
|
+
parser_options = parser_options.merge(expandContext: parser_options.delete(:context)) if parser_options.has_key?(:context)
|
28
28
|
input = JSON::LD::API.fromRdf(reader) if reader
|
29
|
-
output = JSON::LD::API.expand(input,
|
29
|
+
output = JSON::LD::API.expand(input, parser_options)
|
30
30
|
secs = Time.new - start
|
31
31
|
options[:output].puts output.to_json(JSON::LD::JSON_STATE)
|
32
32
|
STDERR.puts "Expanded in #{secs} seconds." unless options[:quiet]
|
33
33
|
elsif options[:compact]
|
34
34
|
input = JSON::LD::API.fromRdf(reader) if reader
|
35
|
-
output = JSON::LD::API.compact(input,
|
35
|
+
output = JSON::LD::API.compact(input, parser_options[:context], parser_options)
|
36
36
|
secs = Time.new - start
|
37
37
|
options[:output].puts output.to_json(JSON::LD::JSON_STATE)
|
38
38
|
STDERR.puts "Compacted in #{secs} seconds." unless options[:quiet]
|
39
39
|
elsif options[:flatten]
|
40
40
|
input = JSON::LD::API.fromRdf(reader) if reader
|
41
|
-
output = JSON::LD::API.flatten(input,
|
41
|
+
output = JSON::LD::API.flatten(input, parser_options[:context], parser_options)
|
42
42
|
secs = Time.new - start
|
43
43
|
options[:output].puts output.to_json(JSON::LD::JSON_STATE)
|
44
44
|
STDERR.puts "Flattened in #{secs} seconds." unless options[:quiet]
|
45
45
|
elsif options[:frame]
|
46
46
|
input = JSON::LD::API.fromRdf(reader) if reader
|
47
|
-
output = JSON::LD::API.frame(input,
|
47
|
+
output = JSON::LD::API.frame(input, parser_options[:frame], parser_options)
|
48
48
|
secs = Time.new - start
|
49
49
|
options[:output].puts output.to_json(JSON::LD::JSON_STATE)
|
50
50
|
STDERR.puts "Framed in #{secs} seconds." unless options[:quiet]
|
51
51
|
else
|
52
|
-
|
53
|
-
parser_options
|
52
|
+
parser_options = parser_options.merge(expandContext: parser_options.delete(:context)) if parser_options.has_key?(:context)
|
53
|
+
parser_options[:standard_prefixes] = true
|
54
54
|
reader ||= JSON::LD::Reader.new(input, parser_options)
|
55
55
|
num = 0
|
56
56
|
RDF::Writer.for(options[:output_format]).new(options[:output], parser_options) do |w|
|
@@ -86,7 +86,6 @@ parser_options = {
|
|
86
86
|
}
|
87
87
|
|
88
88
|
options = {
|
89
|
-
parser_options: parser_options,
|
90
89
|
output: STDOUT,
|
91
90
|
output_format: :jsonld,
|
92
91
|
input_format: :jsonld,
|
@@ -141,49 +140,47 @@ opts = GetoptLong.new(*OPT_ARGS.map {|o| o[0..-2]})
|
|
141
140
|
opts.each do |opt, arg|
|
142
141
|
case opt
|
143
142
|
when '--debug' then logger.level = Logger::DEBUG
|
144
|
-
when '--compact' then
|
145
|
-
when "--compactArrays" then
|
146
|
-
when '--context' then
|
143
|
+
when '--compact' then parser_options[:compact] = true
|
144
|
+
when "--compactArrays" then parser_options[:compactArrays] = (arg || 'true') == 'true'
|
145
|
+
when '--context' then parser_options[:context] = RDF::URI(arg).absolute? ? arg : File.open(arg)
|
147
146
|
when '--evaluate' then input = arg
|
148
147
|
when '--expand' then options[:expand] = true
|
149
|
-
when "--expanded" then
|
150
|
-
when "--explicit" then
|
148
|
+
when "--expanded" then parser_options[:expanded] = (arg || 'true') == 'true'
|
149
|
+
when "--explicit" then parser_options[:compactArrays] = (arg || 'true') == 'true'
|
151
150
|
when '--format' then options[:output_format] = arg.to_sym
|
152
151
|
when '--flatten' then options[:flatten] = arg
|
153
|
-
when '--frame' then options[:frame] = arg
|
152
|
+
when '--frame' then options[:frame] = parser_otpions[:frame] = RDF::URI(arg).absolute? ? arg : File.open(arg)
|
154
153
|
when '--input-format' then options[:input_format] = arg.to_sym
|
155
|
-
when "--omitDefault" then
|
154
|
+
when "--omitDefault" then parser_options[:omitDefault] = (arg || 'true') == 'true'
|
156
155
|
when '--output' then options[:output] = File.open(arg, "w")
|
157
156
|
when '--parse-only' then options[:parse_only] = true
|
158
|
-
when '--processingMode' then
|
157
|
+
when '--processingMode' then parser_options[:processingMode] = arg
|
159
158
|
when '--quiet'
|
160
159
|
options[:quiet] = true
|
161
160
|
logger.level = Logger::FATAL
|
162
|
-
when "--rename_bnodes" then
|
163
|
-
when "--requireAll" then
|
161
|
+
when "--rename_bnodes" then parser_options[:rename_bnodes] = (arg || 'true') == 'true'
|
162
|
+
when "--requireAll" then parser_options[:requireAll] = (arg || 'true') == 'true'
|
164
163
|
when '--stream' then parser_options[:stream] = true
|
165
|
-
when "--unique_bnodes" then
|
164
|
+
when "--unique_bnodes" then parser_options[:unique_bnodes] = (arg || 'true') == 'true'
|
166
165
|
when '--uri' then parser_options[:base] = arg
|
167
166
|
when '--validate' then parser_options[:validate] = true
|
168
167
|
when '--help' then usage
|
169
168
|
when '--embed'
|
170
169
|
case arg
|
171
|
-
when '@always', '@never', '@link', '@
|
172
|
-
|
170
|
+
when '@always', '@never', '@link', '@once'
|
171
|
+
parser_options[:embed] = arg
|
173
172
|
when 'true'
|
174
|
-
|
173
|
+
parser_options[:embed] = '@never'
|
175
174
|
when 'false'
|
176
|
-
|
175
|
+
parser_options[:embed] = '@first'
|
177
176
|
else
|
178
|
-
STDERR.puts "--embed option takes one of @always, @never, @link,
|
177
|
+
STDERR.puts "--embed option takes one of @always, @never, @link, or @once"
|
179
178
|
exit(1)
|
180
179
|
end
|
181
180
|
end
|
182
181
|
end
|
183
182
|
|
184
183
|
# Hack
|
185
|
-
options[:parser_options][:context] = options[:context] if parser_options[:stream]
|
186
|
-
|
187
184
|
if !(options.keys & [:expand, :compact, :flatten, :frame]).empty? &&
|
188
185
|
(parser_options[:stream] || options[:output_format] != :jsonld)
|
189
186
|
STDERR.puts "Incompatible options"
|
@@ -192,11 +189,11 @@ end
|
|
192
189
|
|
193
190
|
if ARGV.empty?
|
194
191
|
s = input ? input : $stdin.read
|
195
|
-
run(StringIO.new(s), options)
|
192
|
+
run(StringIO.new(s), options, parser_options)
|
196
193
|
else
|
197
194
|
ARGV.each do |file|
|
198
195
|
# Call with opened files
|
199
|
-
RDF::Util::File.open_file(file, options) {|f| run(f, options)}
|
196
|
+
RDF::Util::File.open_file(file, options) {|f| run(f, options, parser_options)}
|
200
197
|
end
|
201
198
|
end
|
202
199
|
puts
|