json-ld 2.2.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +55 -55
- data/VERSION +1 -1
- data/lib/json/ld.rb +4 -2
- data/lib/json/ld/api.rb +49 -59
- data/lib/json/ld/compact.rb +60 -56
- data/lib/json/ld/context.rb +52 -40
- data/lib/json/ld/expand.rb +53 -61
- data/lib/json/ld/extensions.rb +31 -16
- data/lib/json/ld/flatten.rb +99 -90
- data/lib/json/ld/format.rb +2 -2
- data/lib/json/ld/frame.rb +47 -30
- data/lib/json/ld/from_rdf.rb +31 -23
- data/lib/json/ld/resource.rb +1 -1
- data/lib/json/ld/to_rdf.rb +4 -2
- data/lib/json/ld/utils.rb +25 -35
- data/lib/json/ld/writer.rb +25 -1
- data/spec/api_spec.rb +1 -0
- data/spec/compact_spec.rb +536 -31
- data/spec/context_spec.rb +109 -43
- data/spec/expand_spec.rb +413 -18
- data/spec/flatten_spec.rb +107 -27
- data/spec/frame_spec.rb +255 -34
- data/spec/from_rdf_spec.rb +102 -3
- data/spec/streaming_writer_spec.rb +8 -9
- data/spec/suite_compact_spec.rb +2 -2
- data/spec/suite_expand_spec.rb +2 -2
- data/spec/suite_flatten_spec.rb +2 -2
- data/spec/suite_frame_spec.rb +2 -2
- data/spec/suite_from_rdf_spec.rb +2 -3
- data/spec/suite_helper.rb +57 -61
- data/spec/suite_remote_doc_spec.rb +2 -2
- data/spec/suite_to_rdf_spec.rb +4 -4
- data/spec/to_rdf_spec.rb +88 -1
- data/spec/writer_spec.rb +5 -6
- metadata +5 -7
- data/spec/suite_error_spec.rb +0 -16
data/lib/json/ld/from_rdf.rb
CHANGED
@@ -10,23 +10,23 @@ module JSON::LD
|
|
10
10
|
# Generate a JSON-LD array representation from an array of `RDF::Statement`.
|
11
11
|
# Representation is in expanded form
|
12
12
|
#
|
13
|
-
# @param [Array<RDF::Statement>, RDF::Enumerable]
|
13
|
+
# @param [Array<RDF::Statement>, RDF::Enumerable] dataset
|
14
14
|
# @param [Boolean] useRdfType (false)
|
15
15
|
# If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
|
16
16
|
# @param [Boolean] useNativeTypes (false) use native representations
|
17
17
|
# @return [Array<Hash>] the JSON-LD document in normalized form
|
18
|
-
def from_statements(
|
18
|
+
def from_statements(dataset, useRdfType: false, useNativeTypes: false)
|
19
19
|
default_graph = {}
|
20
20
|
graph_map = {'@default' => default_graph}
|
21
|
-
|
21
|
+
referenced_once = {}
|
22
22
|
|
23
23
|
value = nil
|
24
24
|
ec = Context.new
|
25
25
|
|
26
26
|
# Create a map for node to object representation
|
27
27
|
|
28
|
-
# For each
|
29
|
-
|
28
|
+
# For each statement in dataset
|
29
|
+
dataset.each do |statement|
|
30
30
|
#log_debug("statement") { statement.to_nquads.chomp}
|
31
31
|
|
32
32
|
name = statement.graph_name ? ec.expand_iri(statement.graph_name).to_s : '@default'
|
@@ -53,16 +53,23 @@ module JSON::LD
|
|
53
53
|
|
54
54
|
merge_value(node, statement.predicate.to_s, value)
|
55
55
|
|
56
|
-
# If object is a blank node identifier or
|
57
|
-
if statement.object.
|
56
|
+
# If object is a blank node identifier or rdf:nil, it might represent the a list node:
|
57
|
+
if statement.object == RDF.nil
|
58
58
|
# Append a new JSON object consisting of three members, node, property, and value to the usages array. The node member is set to a reference to node, property to predicate, and value to a reference to value.
|
59
|
-
|
59
|
+
object = node_map[statement.object.to_s]
|
60
|
+
merge_value(object, :usages, {
|
60
61
|
node: node,
|
61
62
|
property: statement.predicate.to_s,
|
62
63
|
value: value
|
63
64
|
})
|
64
|
-
|
65
|
-
|
65
|
+
elsif referenced_once.has_key?(statement.object.to_s)
|
66
|
+
referenced_once[statement.object.to_s] = false
|
67
|
+
elsif statement.object.node?
|
68
|
+
referenced_once[statement.object.to_s] = {
|
69
|
+
node: node,
|
70
|
+
property: statement.predicate.to_s,
|
71
|
+
value: value
|
72
|
+
}
|
66
73
|
end
|
67
74
|
end
|
68
75
|
|
@@ -78,30 +85,31 @@ module JSON::LD
|
|
78
85
|
# If property equals rdf:rest, the value associated to the usages member of node has exactly 1 entry, node has a rdf:first and rdf:rest property, both of which have as value an array consisting of a single element, and node has no other members apart from an optional @type member whose value is an array with a single item equal to rdf:List, node represents a well-formed list node. Continue with the following steps:
|
79
86
|
#log_debug("list element?") {node.to_json(JSON_STATE) rescue 'malformed json'}
|
80
87
|
while property == RDF.rest.to_s &&
|
81
|
-
Array(node_usages_map[node['@id']]).uniq.length == 1 &&
|
82
88
|
blank_node?(node) &&
|
89
|
+
referenced_once[node['@id']] &&
|
83
90
|
node.keys.none? {|k| !["@id", '@type', :usages, RDF.first.to_s, RDF.rest.to_s].include?(k)} &&
|
84
|
-
Array(node[:usages]).length == 1 &&
|
85
91
|
(f = node[RDF.first.to_s]).is_a?(Array) && f.length == 1 &&
|
86
92
|
(r = node[RDF.rest.to_s]).is_a?(Array) && r.length == 1 &&
|
87
93
|
((t = node['@type']).nil? || t == [RDF.List.to_s])
|
88
94
|
list << Array(node[RDF.first.to_s]).first
|
89
95
|
list_nodes << node['@id']
|
90
|
-
|
96
|
+
|
97
|
+
# get next node, moving backwards through list
|
98
|
+
node_usage = referenced_once[node['@id']]
|
91
99
|
node, property, head = node_usage[:node], node_usage[:property], node_usage[:value]
|
92
100
|
end
|
93
101
|
|
94
102
|
# If property equals rdf:first, i.e., the detected list is nested inside another list
|
95
|
-
if property == RDF.first.to_s
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
103
|
+
#if property == RDF.first.to_s
|
104
|
+
# # and the value of the @id of node equals rdf:nil, i.e., the detected list is empty, continue with the next usage item. The rdf:nil node cannot be converted to a list object as it would result in a list of lists, which isn't supported.
|
105
|
+
# next if node['@id'] == RDF.nil.to_s
|
106
|
+
#
|
107
|
+
# # Otherwise, the list consists of at least one item. We preserve the head node and transform the rest of the linked list to a list object
|
108
|
+
# head_id = head['@id']
|
109
|
+
# head = graph_object[head_id]
|
110
|
+
# head = Array(head[RDF.rest.to_s]).first
|
111
|
+
# list.pop; list_nodes.pop
|
112
|
+
#end
|
105
113
|
|
106
114
|
head.delete('@id')
|
107
115
|
head['@list'] = list.reverse
|
data/lib/json/ld/resource.rb
CHANGED
@@ -76,7 +76,7 @@ module JSON::LD
|
|
76
76
|
# @option options [Boolean] :stub (false)
|
77
77
|
# This is a stand-in for another resource that has
|
78
78
|
# not yet been retrieved (or created) from Mongo
|
79
|
-
def initialize(node_definition, options
|
79
|
+
def initialize(node_definition, **options)
|
80
80
|
@context = options[:context]
|
81
81
|
@clean = options.fetch(:clean, false)
|
82
82
|
@new = options.fetch(:new, true)
|
data/lib/json/ld/to_rdf.rb
CHANGED
@@ -37,6 +37,9 @@ module JSON::LD
|
|
37
37
|
# Initialize literal as an RDF literal using value and datatype. If element has the key @language and datatype is xsd:string, then add the value associated with the @language key as the language of the object.
|
38
38
|
language = item.fetch('@language', nil)
|
39
39
|
return RDF::Literal.new(value, datatype: datatype, language: language)
|
40
|
+
elsif list?(item)
|
41
|
+
# If item is a list object, initialize list_results as an empty array, and object to the result of the List Conversion algorithm, passing the value associated with the @list key from item and list_results.
|
42
|
+
return parse_list(item['@list'], graph_name: graph_name, &block)
|
40
43
|
end
|
41
44
|
|
42
45
|
subject = item['@id'] ? as_resource(item['@id']) : node
|
@@ -64,8 +67,7 @@ module JSON::LD
|
|
64
67
|
vv.each do |v|
|
65
68
|
if list?(v)
|
66
69
|
#log_debug("item_to_rdf") {"list: #{v.inspect}"}
|
67
|
-
|
68
|
-
object = parse_list(v['@list'], graph_name: graph_name, &block)
|
70
|
+
object = item_to_rdf(v, graph_name: graph_name, &block)
|
69
71
|
|
70
72
|
# Append a triple composed of object, prediate, and object to results and add all triples from list_results to results.
|
71
73
|
yield RDF::Statement(object, predicate, subject, graph_name: graph_name)
|
data/lib/json/ld/utils.rb
CHANGED
@@ -110,6 +110,14 @@ module JSON::LD
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
+
##
|
114
|
+
# Represent as an array
|
115
|
+
# @param [Object] object
|
116
|
+
# @return [Array<Object>]
|
117
|
+
def as_array(object)
|
118
|
+
object.is_a?(Array) ? object : [object]
|
119
|
+
end
|
120
|
+
|
113
121
|
##
|
114
122
|
# Compares two JSON-LD values for equality. Two JSON-LD values will be
|
115
123
|
# considered equal if:
|
@@ -142,30 +150,33 @@ module JSON::LD
|
|
142
150
|
# @param [Hash] subject the hash to add the value to.
|
143
151
|
# @param [String] property the property that relates the value to the subject.
|
144
152
|
# @param [Object] value the value to add.
|
145
|
-
# @param [
|
146
|
-
#
|
147
|
-
#
|
148
|
-
# an array
|
149
|
-
# @
|
153
|
+
# @param [Boolean] property_is_array (false)
|
154
|
+
# true if the property is always an array, false if not.
|
155
|
+
# @param [Boolean] value_is_array (false)
|
156
|
+
# true if the value to be added should be preserved as an array (lists)
|
157
|
+
# @param [Boolean] allow_duplicate (true)
|
150
158
|
# true to allow duplicates, false not to (uses
|
151
159
|
# a simple shallow comparison of subject ID or value).
|
152
|
-
def add_value(subject, property, value,
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
subject[property] = [] if value.empty? &&
|
157
|
-
value.each
|
160
|
+
def add_value(subject, property, value, property_is_array: false, value_is_array: false, allow_duplicate: true)
|
161
|
+
if value_is_array
|
162
|
+
subject[property] = value
|
163
|
+
elsif value.is_a?(Array)
|
164
|
+
subject[property] = [] if value.empty? && property_is_array
|
165
|
+
value.each do |v|
|
166
|
+
add_value(subject, property, v,
|
167
|
+
property_is_array: property_is_array, allow_duplicate: allow_duplicate)
|
168
|
+
end
|
158
169
|
elsif subject[property]
|
159
170
|
# check if subject already has value if duplicates not allowed
|
160
|
-
_has_value = !
|
171
|
+
_has_value = !allow_duplicate && has_value(subject, property, value)
|
161
172
|
|
162
173
|
# make property an array if value not present or always an array
|
163
|
-
if !subject[property].is_a?(Array) && (!_has_value ||
|
174
|
+
if !subject[property].is_a?(Array) && (!_has_value || property_is_array)
|
164
175
|
subject[property] = [subject[property]]
|
165
176
|
end
|
166
177
|
subject[property] << value unless _has_value
|
167
178
|
else
|
168
|
-
subject[property] =
|
179
|
+
subject[property] = property_is_array ? [value] : value
|
169
180
|
end
|
170
181
|
end
|
171
182
|
|
@@ -219,27 +230,6 @@ module JSON::LD
|
|
219
230
|
values << value
|
220
231
|
end
|
221
232
|
end
|
222
|
-
|
223
|
-
# Merge values into compacted results, creating arrays if necessary
|
224
|
-
def merge_compacted_value(hash, key, value)
|
225
|
-
return unless hash
|
226
|
-
case hash[key]
|
227
|
-
when nil then hash[key] = value
|
228
|
-
when Array
|
229
|
-
if value.is_a?(Array)
|
230
|
-
hash[key].concat(value)
|
231
|
-
else
|
232
|
-
hash[key] << value
|
233
|
-
end
|
234
|
-
else
|
235
|
-
hash[key] = [hash[key]]
|
236
|
-
if value.is_a?(Array)
|
237
|
-
hash[key].concat(value)
|
238
|
-
else
|
239
|
-
hash[key] << value
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
233
|
end
|
244
234
|
|
245
235
|
##
|
data/lib/json/ld/writer.rb
CHANGED
@@ -90,12 +90,36 @@ module JSON::LD
|
|
90
90
|
control: :url2,
|
91
91
|
on: ["--context CONTEXT"],
|
92
92
|
description: "Context to use when compacting.") {|arg| RDF::URI(arg)},
|
93
|
+
RDF::CLI::Option.new(
|
94
|
+
symbol: :embed,
|
95
|
+
datatype: %w(@always @last @never),
|
96
|
+
control: :select,
|
97
|
+
on: ["--embed EMBED"],
|
98
|
+
description: "How to embed matched objects (@last).") {|arg| RDF::URI(arg)},
|
99
|
+
RDF::CLI::Option.new(
|
100
|
+
symbol: :explicit,
|
101
|
+
datatype: TrueClass,
|
102
|
+
control: :checkbox,
|
103
|
+
on: ["--explicit"],
|
104
|
+
description: "Only include explicitly declared properties in output (false)") {|arg| RDF::URI(arg)},
|
105
|
+
RDF::CLI::Option.new(
|
106
|
+
symbol: :omitDefault,
|
107
|
+
datatype: TrueClass,
|
108
|
+
control: :checkbox,
|
109
|
+
on: ["--omitDefault"],
|
110
|
+
description: "Omit missing properties from output (false)") {|arg| RDF::URI(arg)},
|
93
111
|
RDF::CLI::Option.new(
|
94
112
|
symbol: :processing_mode,
|
95
113
|
datatype: %w(json-ld-1.0 json-ld-1.1),
|
96
114
|
control: :radio,
|
97
115
|
on: ["--processingMode MODE", %w(json-ld-1.0 json-ld-1.1)],
|
98
116
|
description: "Set Processing Mode (json-ld-1.0 or json-ld-1.1)"),
|
117
|
+
RDF::CLI::Option.new(
|
118
|
+
symbol: :requireAll,
|
119
|
+
datatype: TrueClass,
|
120
|
+
control: :checkbox,
|
121
|
+
on: ["--requireAll"],
|
122
|
+
description: "Require all properties to match (true)") {|arg| RDF::URI(arg)},
|
99
123
|
RDF::CLI::Option.new(
|
100
124
|
symbol: :stream,
|
101
125
|
datatype: TrueClass,
|
@@ -139,7 +163,7 @@ module JSON::LD
|
|
139
163
|
# @yieldreturn [void]
|
140
164
|
# @yield [writer]
|
141
165
|
# @yieldparam [RDF::Writer] writer
|
142
|
-
def initialize(output = $stdout, options
|
166
|
+
def initialize(output = $stdout, **options, &block)
|
143
167
|
options[:base_uri] ||= options[:base] if options.has_key?(:base)
|
144
168
|
options[:base] ||= options[:base_uri] if options.has_key?(:base_uri)
|
145
169
|
super do
|
data/spec/api_spec.rb
CHANGED
data/spec/compact_spec.rb
CHANGED
@@ -292,7 +292,47 @@ describe JSON::LD::API do
|
|
292
292
|
},
|
293
293
|
"http://example.org/vocab#contains": "this-is-not-an-IRI"
|
294
294
|
})
|
295
|
-
}
|
295
|
+
},
|
296
|
+
"Language map term with language value" => {
|
297
|
+
input: %([{"http://example/t": {"@value": "foo", "@language": "en"}}]),
|
298
|
+
context: %({"t": {"@id": "http://example/t", "@container": "@language"}}),
|
299
|
+
output: %({
|
300
|
+
"@context": {
|
301
|
+
"t": {"@id": "http://example/t", "@container": "@language"}
|
302
|
+
},
|
303
|
+
"t": {"en": "foo"}
|
304
|
+
})
|
305
|
+
},
|
306
|
+
"Datatyped term with datatyped value" => {
|
307
|
+
input: %([{"http://example/t": {"@value": "foo", "@type": "http:/example/type"}}]),
|
308
|
+
context: %({"t": {"@id": "http://example/t", "@type": "http:/example/type"}}),
|
309
|
+
output: %({
|
310
|
+
"@context": {
|
311
|
+
"t": {"@id": "http://example/t", "@type": "http:/example/type"}
|
312
|
+
},
|
313
|
+
"t": "foo"
|
314
|
+
})
|
315
|
+
},
|
316
|
+
"Datatyped term with simple value" => {
|
317
|
+
input: %([{"http://example/t": {"@value": "foo"}}]),
|
318
|
+
context: %({"t": {"@id": "http://example/t", "@type": "http:/example/type"}}),
|
319
|
+
output: %({
|
320
|
+
"@context": {
|
321
|
+
"t": {"@id": "http://example/t", "@type": "http:/example/type"}
|
322
|
+
},
|
323
|
+
"http://example/t": "foo"
|
324
|
+
})
|
325
|
+
},
|
326
|
+
"Datatyped term with object value" => {
|
327
|
+
input: %([{"http://example/t": {"@id": "http://example/id"}}]),
|
328
|
+
context: %({"t": {"@id": "http://example/t", "@type": "http:/example/type"}}),
|
329
|
+
output: %({
|
330
|
+
"@context": {
|
331
|
+
"t": {"@id": "http://example/t", "@type": "http:/example/type"}
|
332
|
+
},
|
333
|
+
"http://example/t": {"@id": "http://example/id"}
|
334
|
+
})
|
335
|
+
},
|
296
336
|
}.each_pair do |title, params|
|
297
337
|
it(title) {run_compact(params)}
|
298
338
|
end
|
@@ -487,6 +527,72 @@ describe JSON::LD::API do
|
|
487
527
|
"foo_de": ["de"]
|
488
528
|
})
|
489
529
|
},
|
530
|
+
"coerced @list containing an empty list" => {
|
531
|
+
input: %([{
|
532
|
+
"http://example.com/foo": [{"@list": [{"@list": []}]}]
|
533
|
+
}]),
|
534
|
+
context: %({
|
535
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
536
|
+
}),
|
537
|
+
output: %({
|
538
|
+
"@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
|
539
|
+
"foo": [[]]
|
540
|
+
}),
|
541
|
+
},
|
542
|
+
"coerced @list containing a list" => {
|
543
|
+
input: %([{
|
544
|
+
"http://example.com/foo": [{"@list": [{"@list": [{"@value": "baz"}]}]}]
|
545
|
+
}]),
|
546
|
+
context: %({
|
547
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
548
|
+
}),
|
549
|
+
output: %({
|
550
|
+
"@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
|
551
|
+
"foo": [["baz"]]
|
552
|
+
}),
|
553
|
+
},
|
554
|
+
"coerced @list containing an deep list" => {
|
555
|
+
input: %([{
|
556
|
+
"http://example.com/foo": [{"@list": [{"@list": [{"@list": [{"@value": "baz"}]}]}]}]
|
557
|
+
}]),
|
558
|
+
context: %({
|
559
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
560
|
+
}),
|
561
|
+
output: %({
|
562
|
+
"@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
|
563
|
+
"foo": [[["baz"]]]
|
564
|
+
}),
|
565
|
+
},
|
566
|
+
"coerced @list containing multiple lists" => {
|
567
|
+
input: %([{
|
568
|
+
"http://example.com/foo": [{"@list": [
|
569
|
+
{"@list": [{"@value": "a"}]},
|
570
|
+
{"@list": [{"@value": "b"}]}
|
571
|
+
]}]
|
572
|
+
}]),
|
573
|
+
context: %({
|
574
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
575
|
+
}),
|
576
|
+
output: %({
|
577
|
+
"@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
|
578
|
+
"foo": [["a"], ["b"]]
|
579
|
+
}),
|
580
|
+
},
|
581
|
+
"coerced @list containing mixed list values" => {
|
582
|
+
input: %([{
|
583
|
+
"http://example.com/foo": [{"@list": [
|
584
|
+
{"@list": [{"@value": "a"}]},
|
585
|
+
{"@value": "b"}
|
586
|
+
]}]
|
587
|
+
}]),
|
588
|
+
context: %({
|
589
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
590
|
+
}),
|
591
|
+
output: %({
|
592
|
+
"@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
|
593
|
+
"foo": [["a"], "b"]
|
594
|
+
}),
|
595
|
+
},
|
490
596
|
}.each_pair do |title, params|
|
491
597
|
it(title) {run_compact(params)}
|
492
598
|
end
|
@@ -526,6 +632,96 @@ describe JSON::LD::API do
|
|
526
632
|
}
|
527
633
|
})
|
528
634
|
},
|
635
|
+
"simple map with @none node definition" => {
|
636
|
+
input: %([{
|
637
|
+
"@id": "http://example.com/article",
|
638
|
+
"http://example.com/vocab/author": [{
|
639
|
+
"@id": "http://example.org/person/1",
|
640
|
+
"@index": "regular"
|
641
|
+
}, {
|
642
|
+
"@id": "http://example.org/guest/cd24f329aa"
|
643
|
+
}]
|
644
|
+
}]),
|
645
|
+
context: %({
|
646
|
+
"author": {"@id": "http://example.com/vocab/author", "@container": "@index" }
|
647
|
+
}),
|
648
|
+
output: %({
|
649
|
+
"@context": {
|
650
|
+
"author": {
|
651
|
+
"@id": "http://example.com/vocab/author",
|
652
|
+
"@container": "@index"
|
653
|
+
}
|
654
|
+
},
|
655
|
+
"@id": "http://example.com/article",
|
656
|
+
"author": {
|
657
|
+
"regular": {
|
658
|
+
"@id": "http://example.org/person/1"
|
659
|
+
},
|
660
|
+
"@none": {
|
661
|
+
"@id": "http://example.org/guest/cd24f329aa"
|
662
|
+
}
|
663
|
+
}
|
664
|
+
}),
|
665
|
+
processingMode: 'json-ld-1.1'
|
666
|
+
},
|
667
|
+
"simple map with @none value" => {
|
668
|
+
input: %([{
|
669
|
+
"@id": "http://example.com/article",
|
670
|
+
"http://example.com/vocab/author": [{
|
671
|
+
"@value": "Gregg",
|
672
|
+
"@index": "regular"
|
673
|
+
}, {
|
674
|
+
"@value": "Manu"
|
675
|
+
}]
|
676
|
+
}]),
|
677
|
+
context: %({
|
678
|
+
"author": {"@id": "http://example.com/vocab/author", "@container": "@index" }
|
679
|
+
}),
|
680
|
+
output: %({
|
681
|
+
"@context": {
|
682
|
+
"author": {
|
683
|
+
"@id": "http://example.com/vocab/author",
|
684
|
+
"@container": "@index"
|
685
|
+
}
|
686
|
+
},
|
687
|
+
"@id": "http://example.com/article",
|
688
|
+
"author": {
|
689
|
+
"regular": "Gregg",
|
690
|
+
"@none": "Manu"
|
691
|
+
}
|
692
|
+
}),
|
693
|
+
processingMode: 'json-ld-1.1'
|
694
|
+
},
|
695
|
+
"simple map with @none value using alias of @none" => {
|
696
|
+
input: %([{
|
697
|
+
"@id": "http://example.com/article",
|
698
|
+
"http://example.com/vocab/author": [{
|
699
|
+
"@value": "Gregg",
|
700
|
+
"@index": "regular"
|
701
|
+
}, {
|
702
|
+
"@value": "Manu"
|
703
|
+
}]
|
704
|
+
}]),
|
705
|
+
context: %({
|
706
|
+
"author": {"@id": "http://example.com/vocab/author", "@container": "@index" },
|
707
|
+
"none": "@none"
|
708
|
+
}),
|
709
|
+
output: %({
|
710
|
+
"@context": {
|
711
|
+
"author": {
|
712
|
+
"@id": "http://example.com/vocab/author",
|
713
|
+
"@container": "@index"
|
714
|
+
},
|
715
|
+
"none": "@none"
|
716
|
+
},
|
717
|
+
"@id": "http://example.com/article",
|
718
|
+
"author": {
|
719
|
+
"regular": "Gregg",
|
720
|
+
"none": "Manu"
|
721
|
+
}
|
722
|
+
}),
|
723
|
+
processingMode: 'json-ld-1.1'
|
724
|
+
},
|
529
725
|
}.each_pair do |title, params|
|
530
726
|
it(title) {run_compact(params)}
|
531
727
|
end
|
@@ -560,6 +756,66 @@ describe JSON::LD::API do
|
|
560
756
|
}
|
561
757
|
})
|
562
758
|
},
|
759
|
+
"with no @language" => {
|
760
|
+
input: %([
|
761
|
+
{
|
762
|
+
"@id": "http://example.com/queen",
|
763
|
+
"http://example.com/vocab/label": [
|
764
|
+
{"@value": "The Queen", "@language": "en"},
|
765
|
+
{"@value": "Die Königin", "@language": "de"},
|
766
|
+
{"@value": "Ihre Majestät"}
|
767
|
+
]
|
768
|
+
}
|
769
|
+
]),
|
770
|
+
context: %({
|
771
|
+
"vocab": "http://example.com/vocab/",
|
772
|
+
"label": {"@id": "vocab:label", "@container": "@language"}
|
773
|
+
}),
|
774
|
+
output: %({
|
775
|
+
"@context": {
|
776
|
+
"vocab": "http://example.com/vocab/",
|
777
|
+
"label": {"@id": "vocab:label", "@container": "@language"}
|
778
|
+
},
|
779
|
+
"@id": "http://example.com/queen",
|
780
|
+
"label": {
|
781
|
+
"en": "The Queen",
|
782
|
+
"de": "Die Königin",
|
783
|
+
"@none": "Ihre Majestät"
|
784
|
+
}
|
785
|
+
}),
|
786
|
+
processingMode: "json-ld-1.1"
|
787
|
+
},
|
788
|
+
"with no @language using alias of @none" => {
|
789
|
+
input: %([
|
790
|
+
{
|
791
|
+
"@id": "http://example.com/queen",
|
792
|
+
"http://example.com/vocab/label": [
|
793
|
+
{"@value": "The Queen", "@language": "en"},
|
794
|
+
{"@value": "Die Königin", "@language": "de"},
|
795
|
+
{"@value": "Ihre Majestät"}
|
796
|
+
]
|
797
|
+
}
|
798
|
+
]),
|
799
|
+
context: %({
|
800
|
+
"vocab": "http://example.com/vocab/",
|
801
|
+
"label": {"@id": "vocab:label", "@container": "@language"},
|
802
|
+
"none": "@none"
|
803
|
+
}),
|
804
|
+
output: %({
|
805
|
+
"@context": {
|
806
|
+
"vocab": "http://example.com/vocab/",
|
807
|
+
"label": {"@id": "vocab:label", "@container": "@language"},
|
808
|
+
"none": "@none"
|
809
|
+
},
|
810
|
+
"@id": "http://example.com/queen",
|
811
|
+
"label": {
|
812
|
+
"en": "The Queen",
|
813
|
+
"de": "Die Königin",
|
814
|
+
"none": "Ihre Majestät"
|
815
|
+
}
|
816
|
+
}),
|
817
|
+
processingMode: "json-ld-1.1"
|
818
|
+
},
|
563
819
|
}.each_pair do |title, params|
|
564
820
|
it(title) {run_compact(params)}
|
565
821
|
end
|
@@ -633,6 +889,52 @@ describe JSON::LD::API do
|
|
633
889
|
}
|
634
890
|
})
|
635
891
|
},
|
892
|
+
"Indexes using @none" => {
|
893
|
+
input: %([{
|
894
|
+
"http://example/idmap": [
|
895
|
+
{"http://example/label": [{"@value": "Object with no @id"}]}
|
896
|
+
]
|
897
|
+
}]),
|
898
|
+
context: %({
|
899
|
+
"@vocab": "http://example/",
|
900
|
+
"ex": "http://example.org/",
|
901
|
+
"idmap": {"@container": "@id"}
|
902
|
+
}),
|
903
|
+
output: %({
|
904
|
+
"@context": {
|
905
|
+
"@vocab": "http://example/",
|
906
|
+
"ex": "http://example.org/",
|
907
|
+
"idmap": {"@container": "@id"}
|
908
|
+
},
|
909
|
+
"idmap": {
|
910
|
+
"@none": {"label": "Object with no @id"}
|
911
|
+
}
|
912
|
+
})
|
913
|
+
},
|
914
|
+
"Indexes using @none with alias" => {
|
915
|
+
input: %([{
|
916
|
+
"http://example/idmap": [
|
917
|
+
{"http://example/label": [{"@value": "Object with no @id"}]}
|
918
|
+
]
|
919
|
+
}]),
|
920
|
+
context: %({
|
921
|
+
"@vocab": "http://example/",
|
922
|
+
"ex": "http://example.org/",
|
923
|
+
"idmap": {"@container": "@id"},
|
924
|
+
"none": "@none"
|
925
|
+
}),
|
926
|
+
output: %({
|
927
|
+
"@context": {
|
928
|
+
"@vocab": "http://example/",
|
929
|
+
"ex": "http://example.org/",
|
930
|
+
"idmap": {"@container": "@id"},
|
931
|
+
"none": "@none"
|
932
|
+
},
|
933
|
+
"idmap": {
|
934
|
+
"none": {"label": "Object with no @id"}
|
935
|
+
}
|
936
|
+
})
|
937
|
+
},
|
636
938
|
}.each_pair do |title, params|
|
637
939
|
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
638
940
|
end
|
@@ -738,6 +1040,52 @@ describe JSON::LD::API do
|
|
738
1040
|
}
|
739
1041
|
})
|
740
1042
|
},
|
1043
|
+
"Indexes using @none" => {
|
1044
|
+
input: %([{
|
1045
|
+
"http://example/typemap": [
|
1046
|
+
{"http://example/label": [{"@value": "Object with no @type"}]}
|
1047
|
+
]
|
1048
|
+
}]),
|
1049
|
+
context: %({
|
1050
|
+
"@vocab": "http://example/",
|
1051
|
+
"ex": "http://example.org/",
|
1052
|
+
"typemap": {"@container": "@type"}
|
1053
|
+
}),
|
1054
|
+
output: %({
|
1055
|
+
"@context": {
|
1056
|
+
"@vocab": "http://example/",
|
1057
|
+
"ex": "http://example.org/",
|
1058
|
+
"typemap": {"@container": "@type"}
|
1059
|
+
},
|
1060
|
+
"typemap": {
|
1061
|
+
"@none": {"label": "Object with no @type"}
|
1062
|
+
}
|
1063
|
+
})
|
1064
|
+
},
|
1065
|
+
"Indexes using @none with alias" => {
|
1066
|
+
input: %([{
|
1067
|
+
"http://example/typemap": [
|
1068
|
+
{"http://example/label": [{"@value": "Object with no @id"}]}
|
1069
|
+
]
|
1070
|
+
}]),
|
1071
|
+
context: %({
|
1072
|
+
"@vocab": "http://example/",
|
1073
|
+
"ex": "http://example.org/",
|
1074
|
+
"typemap": {"@container": "@type"},
|
1075
|
+
"none": "@none"
|
1076
|
+
}),
|
1077
|
+
output: %({
|
1078
|
+
"@context": {
|
1079
|
+
"@vocab": "http://example/",
|
1080
|
+
"ex": "http://example.org/",
|
1081
|
+
"typemap": {"@container": "@type"},
|
1082
|
+
"none": "@none"
|
1083
|
+
},
|
1084
|
+
"typemap": {
|
1085
|
+
"none": {"label": "Object with no @id"}
|
1086
|
+
}
|
1087
|
+
})
|
1088
|
+
},
|
741
1089
|
}.each_pair do |title, params|
|
742
1090
|
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
743
1091
|
end
|
@@ -832,10 +1180,57 @@ describe JSON::LD::API do
|
|
832
1180
|
},
|
833
1181
|
"input": {
|
834
1182
|
"@id": "http://example.org/id",
|
835
|
-
"@graph":
|
1183
|
+
"@graph": {"value": "x"}
|
836
1184
|
}
|
837
1185
|
})
|
838
1186
|
},
|
1187
|
+
"Odd framing test" => {
|
1188
|
+
input: %([
|
1189
|
+
{
|
1190
|
+
"http://example.org/claim": [
|
1191
|
+
{
|
1192
|
+
"@graph": [
|
1193
|
+
{
|
1194
|
+
"@id": "http://example.org/1",
|
1195
|
+
"https://example.com#test": [
|
1196
|
+
{
|
1197
|
+
"@value": "foo"
|
1198
|
+
}
|
1199
|
+
]
|
1200
|
+
}
|
1201
|
+
]
|
1202
|
+
}
|
1203
|
+
]
|
1204
|
+
}
|
1205
|
+
]
|
1206
|
+
),
|
1207
|
+
context: %( {
|
1208
|
+
"@version": 1.1,
|
1209
|
+
"@vocab": "https://example.com#",
|
1210
|
+
"ex": "http://example.org/",
|
1211
|
+
"claim": {
|
1212
|
+
"@id": "ex:claim",
|
1213
|
+
"@container": "@graph"
|
1214
|
+
},
|
1215
|
+
"id": "@id"
|
1216
|
+
}),
|
1217
|
+
output: %({
|
1218
|
+
"@context": {
|
1219
|
+
"@version": 1.1,
|
1220
|
+
"@vocab": "https://example.com#",
|
1221
|
+
"ex": "http://example.org/",
|
1222
|
+
"claim": {
|
1223
|
+
"@id": "ex:claim",
|
1224
|
+
"@container": "@graph"
|
1225
|
+
},
|
1226
|
+
"id": "@id"
|
1227
|
+
},
|
1228
|
+
"claim": {
|
1229
|
+
"id": "ex:1",
|
1230
|
+
"test": "foo"
|
1231
|
+
}
|
1232
|
+
})
|
1233
|
+
}
|
839
1234
|
}.each_pair do |title, params|
|
840
1235
|
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
841
1236
|
end
|
@@ -888,6 +1283,28 @@ describe JSON::LD::API do
|
|
888
1283
|
}
|
889
1284
|
})
|
890
1285
|
},
|
1286
|
+
"Compacts simple graph with no @index" => {
|
1287
|
+
input: %([{
|
1288
|
+
"http://example.org/input": [{
|
1289
|
+
"@graph": [{
|
1290
|
+
"http://example.org/value": [{"@value": "x"}]
|
1291
|
+
}]
|
1292
|
+
}]
|
1293
|
+
}]),
|
1294
|
+
context: %({
|
1295
|
+
"@vocab": "http://example.org/",
|
1296
|
+
"input": {"@container": ["@graph", "@index", "@set"]}
|
1297
|
+
}),
|
1298
|
+
output: %({
|
1299
|
+
"@context": {
|
1300
|
+
"@vocab": "http://example.org/",
|
1301
|
+
"input": {"@container": ["@graph", "@index", "@set"]}
|
1302
|
+
},
|
1303
|
+
"input": {
|
1304
|
+
"@none": [{"value": "x"}]
|
1305
|
+
}
|
1306
|
+
})
|
1307
|
+
},
|
891
1308
|
"Does not compact graph with @id" => {
|
892
1309
|
input: %([{
|
893
1310
|
"http://example.org/input": [{
|
@@ -910,7 +1327,7 @@ describe JSON::LD::API do
|
|
910
1327
|
"input": {
|
911
1328
|
"@id": "http://example.org/id",
|
912
1329
|
"@index": "g1",
|
913
|
-
"@graph":
|
1330
|
+
"@graph": {"value": "x"}
|
914
1331
|
}
|
915
1332
|
})
|
916
1333
|
},
|
@@ -939,7 +1356,7 @@ describe JSON::LD::API do
|
|
939
1356
|
"input": {"@container": ["@graph", "@id"]}
|
940
1357
|
},
|
941
1358
|
"input": {
|
942
|
-
"
|
1359
|
+
"@none": {"value": "x"}
|
943
1360
|
}
|
944
1361
|
})
|
945
1362
|
},
|
@@ -960,7 +1377,7 @@ describe JSON::LD::API do
|
|
960
1377
|
"@vocab": "http://example.org/",
|
961
1378
|
"input": {"@container": ["@graph", "@id", "@set"]}
|
962
1379
|
},
|
963
|
-
"input": {"
|
1380
|
+
"input": {"@none": [{"value": "x"}]}
|
964
1381
|
})
|
965
1382
|
},
|
966
1383
|
"Compacts simple graph with @index" => {
|
@@ -982,7 +1399,7 @@ describe JSON::LD::API do
|
|
982
1399
|
"input": {"@container": ["@graph", "@id"]}
|
983
1400
|
},
|
984
1401
|
"input": {
|
985
|
-
"
|
1402
|
+
"@none": {"value": "x"}
|
986
1403
|
}
|
987
1404
|
})
|
988
1405
|
},
|
@@ -1032,6 +1449,52 @@ describe JSON::LD::API do
|
|
1032
1449
|
}
|
1033
1450
|
})
|
1034
1451
|
},
|
1452
|
+
"Compacts graph without @id" => {
|
1453
|
+
input: %([{
|
1454
|
+
"http://example.org/input": [{
|
1455
|
+
"@graph": [{
|
1456
|
+
"http://example.org/value": [{"@value": "x"}]
|
1457
|
+
}]
|
1458
|
+
}]
|
1459
|
+
}]),
|
1460
|
+
context: %({
|
1461
|
+
"@vocab": "http://example.org/",
|
1462
|
+
"input": {"@container": ["@graph", "@id"]}
|
1463
|
+
}),
|
1464
|
+
output: %({
|
1465
|
+
"@context": {
|
1466
|
+
"@vocab": "http://example.org/",
|
1467
|
+
"input": {"@container": ["@graph", "@id"]}
|
1468
|
+
},
|
1469
|
+
"input": {
|
1470
|
+
"@none" : {"value": "x"}
|
1471
|
+
}
|
1472
|
+
})
|
1473
|
+
},
|
1474
|
+
"Compacts graph without @id using alias of @none" => {
|
1475
|
+
input: %([{
|
1476
|
+
"http://example.org/input": [{
|
1477
|
+
"@graph": [{
|
1478
|
+
"http://example.org/value": [{"@value": "x"}]
|
1479
|
+
}]
|
1480
|
+
}]
|
1481
|
+
}]),
|
1482
|
+
context: %({
|
1483
|
+
"@vocab": "http://example.org/",
|
1484
|
+
"input": {"@container": ["@graph", "@id"]},
|
1485
|
+
"none": "@none"
|
1486
|
+
}),
|
1487
|
+
output: %({
|
1488
|
+
"@context": {
|
1489
|
+
"@vocab": "http://example.org/",
|
1490
|
+
"input": {"@container": ["@graph", "@id"]},
|
1491
|
+
"none": "@none"
|
1492
|
+
},
|
1493
|
+
"input": {
|
1494
|
+
"none" : {"value": "x"}
|
1495
|
+
}
|
1496
|
+
})
|
1497
|
+
},
|
1035
1498
|
}.each_pair do |title, params|
|
1036
1499
|
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
1037
1500
|
end
|
@@ -1040,7 +1503,7 @@ describe JSON::LD::API do
|
|
1040
1503
|
|
1041
1504
|
context "@nest" do
|
1042
1505
|
{
|
1043
|
-
"Indexes to @nest for property with @
|
1506
|
+
"Indexes to @nest for property with @nest" => {
|
1044
1507
|
input: %([{
|
1045
1508
|
"http://example.org/p1": [{"@value": "v1"}],
|
1046
1509
|
"http://example.org/p2": [{"@value": "v2"}]
|
@@ -1060,7 +1523,7 @@ describe JSON::LD::API do
|
|
1060
1523
|
}
|
1061
1524
|
})
|
1062
1525
|
},
|
1063
|
-
"Indexes to @nest for all properties with @
|
1526
|
+
"Indexes to @nest for all properties with @nest" => {
|
1064
1527
|
input: %([{
|
1065
1528
|
"http://example.org/p1": [{"@value": "v1"}],
|
1066
1529
|
"http://example.org/p2": [{"@value": "v2"}]
|
@@ -1566,6 +2029,28 @@ describe JSON::LD::API do
|
|
1566
2029
|
"c": "C in example"
|
1567
2030
|
}),
|
1568
2031
|
},
|
2032
|
+
"orders lexicographically" => {
|
2033
|
+
input: %([{
|
2034
|
+
"@type": ["http://example/t2", "http://example/t1"],
|
2035
|
+
"http://example.org/foo": [
|
2036
|
+
{"@id": "urn:bar"}
|
2037
|
+
]
|
2038
|
+
}]),
|
2039
|
+
context: %({
|
2040
|
+
"@vocab": "http://example/",
|
2041
|
+
"t1": {"@context": {"foo": {"@id": "http://example.com/foo"}}},
|
2042
|
+
"t2": {"@context": {"foo": {"@id": "http://example.org/foo", "@type": "@id"}}}
|
2043
|
+
}),
|
2044
|
+
output: %({
|
2045
|
+
"@context": {
|
2046
|
+
"@vocab": "http://example/",
|
2047
|
+
"t1": {"@context": {"foo": {"@id": "http://example.com/foo"}}},
|
2048
|
+
"t2": {"@context": {"foo": {"@id": "http://example.org/foo", "@type": "@id"}}}
|
2049
|
+
},
|
2050
|
+
"@type": ["t2", "t1"],
|
2051
|
+
"foo": "urn:bar"
|
2052
|
+
}),
|
2053
|
+
},
|
1569
2054
|
"with @container: @type" => {
|
1570
2055
|
input: %([{
|
1571
2056
|
"http://example/typemap": [
|
@@ -1605,41 +2090,53 @@ describe JSON::LD::API do
|
|
1605
2090
|
validate: true,
|
1606
2091
|
exception: JSON::LD::JsonLdError::InvalidTermDefinition
|
1607
2092
|
},
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
|
1614
|
-
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
2093
|
+
"applies context for all values" => {
|
2094
|
+
input: %([
|
2095
|
+
{
|
2096
|
+
"@id": "http://example.org/id",
|
2097
|
+
"@type": ["http://example/type"],
|
2098
|
+
"http://example/a": [{
|
2099
|
+
"@id": "http://example.org/Foo",
|
2100
|
+
"@type": ["http://example/Foo"],
|
2101
|
+
"http://example/bar": [{"@id": "http://example.org/baz"}]
|
2102
|
+
}]
|
2103
|
+
}
|
2104
|
+
]),
|
2105
|
+
context: %({
|
2106
|
+
"@vocab": "http://example/",
|
2107
|
+
"id": "@id",
|
2108
|
+
"type": "@type",
|
2109
|
+
"Foo": {"@context": {"id": null, "type": null}}
|
1618
2110
|
}),
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
2111
|
+
output: %({
|
2112
|
+
"@context": {
|
2113
|
+
"@vocab": "http://example/",
|
2114
|
+
"id": "@id",
|
2115
|
+
"type": "@type",
|
2116
|
+
"Foo": {"@context": {"id": null, "type": null}}
|
2117
|
+
},
|
2118
|
+
"id": "http://example.org/id",
|
2119
|
+
"type": "http://example/type",
|
2120
|
+
"a": {
|
2121
|
+
"@id": "http://example.org/Foo",
|
2122
|
+
"@type": "Foo",
|
2123
|
+
"bar": {"@id": "http://example.org/baz"}
|
2124
|
+
}
|
1626
2125
|
}),
|
1627
|
-
context: {},
|
1628
|
-
exception: JSON::LD::JsonLdError::ListOfLists
|
1629
2126
|
},
|
1630
|
-
}.
|
1631
|
-
it(title) {run_compact(params)}
|
2127
|
+
}.each_pair do |title, params|
|
2128
|
+
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
1632
2129
|
end
|
1633
2130
|
end
|
1634
2131
|
|
1635
2132
|
context "compact IRI selection" do
|
1636
2133
|
{
|
1637
|
-
"
|
2134
|
+
"does not compact using expanded term in 1.0" => {
|
1638
2135
|
input: %({"http://example.org/foo": "term"}),
|
1639
2136
|
context: %({"ex": {"@id": "http://example.org/"}}),
|
1640
2137
|
output: %({
|
1641
2138
|
"@context": {"ex": {"@id": "http://example.org/"}},
|
1642
|
-
"
|
2139
|
+
"http://example.org/foo": "term"
|
1643
2140
|
}),
|
1644
2141
|
processingMode: "json-ld-1.0"
|
1645
2142
|
},
|
@@ -1716,6 +2213,14 @@ describe JSON::LD::API do
|
|
1716
2213
|
"ex:bar": "term"
|
1717
2214
|
})
|
1718
2215
|
},
|
2216
|
+
"compacts using base if @vocab: relative" => {
|
2217
|
+
input: %({"http://example.org/foo/bar": "term"}),
|
2218
|
+
context: %({"@base": "http://example.org/foo/", "@vocab": ""}),
|
2219
|
+
output: %({
|
2220
|
+
"@context": {"@base": "http://example.org/foo/", "@vocab": ""},
|
2221
|
+
"bar": "term"
|
2222
|
+
})
|
2223
|
+
},
|
1719
2224
|
}.each do |title, params|
|
1720
2225
|
it(title) {run_compact(params)}
|
1721
2226
|
end
|