json-ld 3.2.3 → 3.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/json/ld/api.rb +23 -16
- data/lib/json/ld/compact.rb +16 -16
- data/lib/json/ld/context.rb +52 -84
- data/lib/json/ld/expand.rb +23 -23
- data/lib/json/ld/from_rdf.rb +56 -17
- data/lib/json/ld/streaming_writer.rb +6 -6
- data/lib/json/ld/to_rdf.rb +10 -8
- data/lib/json/ld/writer.rb +3 -3
- data/spec/context_spec.rb +31 -11
- data/spec/frame_spec.rb +43 -0
- data/spec/from_rdf_spec.rb +67 -0
- data/spec/to_rdf_spec.rb +133 -0
- metadata +27 -15
data/lib/json/ld/expand.rb
CHANGED
@@ -29,13 +29,13 @@ module JSON::LD
|
|
29
29
|
# @return [Array<Hash{String => Object}>]
|
30
30
|
def expand(input, active_property, context,
|
31
31
|
framing: false, from_map: false, log_depth: nil)
|
32
|
-
log_debug("expand", depth: log_depth.to_i) {"input: #{input.inspect}, active_property: #{active_property.inspect}, context: #{context.inspect}"}
|
32
|
+
# log_debug("expand", depth: log_depth.to_i) {"input: #{input.inspect}, active_property: #{active_property.inspect}, context: #{context.inspect}"}
|
33
33
|
framing = false if active_property == '@default'
|
34
34
|
expanded_active_property = context.expand_iri(active_property, vocab: true, as_string: true, base: @options[:base]) if active_property
|
35
35
|
|
36
36
|
# Use a term-specific context, if defined, based on the non-type-scoped context.
|
37
37
|
property_scoped_context = context.term_definitions[active_property].context if active_property && context.term_definitions[active_property]
|
38
|
-
log_debug("expand", depth: log_depth.to_i) {"property_scoped_context: #{property_scoped_context.inspect}"} unless property_scoped_context.nil?
|
38
|
+
# log_debug("expand", depth: log_depth.to_i) {"property_scoped_context: #{property_scoped_context.inspect}"} unless property_scoped_context.nil?
|
39
39
|
|
40
40
|
result = case input
|
41
41
|
when Array
|
@@ -76,7 +76,7 @@ module JSON::LD
|
|
76
76
|
!(expanded_key_map.values == ['@id'])
|
77
77
|
|
78
78
|
# If there's a previous context, the context was type-scoped
|
79
|
-
log_debug("expand", depth: log_depth.to_i) {"previous_context: #{context.previous_context.inspect}"} if revert_context
|
79
|
+
# log_debug("expand", depth: log_depth.to_i) {"previous_context: #{context.previous_context.inspect}"} if revert_context
|
80
80
|
context = context.previous_context if revert_context
|
81
81
|
end
|
82
82
|
|
@@ -84,12 +84,12 @@ module JSON::LD
|
|
84
84
|
unless property_scoped_context.nil?
|
85
85
|
context = context.parse(property_scoped_context, base: @options[:base], override_protected: true)
|
86
86
|
end
|
87
|
-
log_debug("expand", depth: log_depth.to_i) {"after property_scoped_context: #{context.inspect}"} unless property_scoped_context.nil?
|
87
|
+
# log_debug("expand", depth: log_depth.to_i) {"after property_scoped_context: #{context.inspect}"} unless property_scoped_context.nil?
|
88
88
|
|
89
89
|
# If element contains the key @context, set active context to the result of the Context Processing algorithm, passing active context and the value of the @context key as local context.
|
90
90
|
if input.key?('@context')
|
91
91
|
context = context.parse(input['@context'], base: @options[:base])
|
92
|
-
log_debug("expand", depth: log_depth.to_i) {"context: #{context.inspect}"}
|
92
|
+
# log_debug("expand", depth: log_depth.to_i) {"context: #{context.inspect}"}
|
93
93
|
end
|
94
94
|
|
95
95
|
# Set the type-scoped context to the context on input, for use later
|
@@ -107,7 +107,7 @@ module JSON::LD
|
|
107
107
|
Array(input[tk]).sort.each do |term|
|
108
108
|
term_context = type_scoped_context.term_definitions[term].context if type_scoped_context.term_definitions[term]
|
109
109
|
unless term_context.nil?
|
110
|
-
log_debug("expand", depth: log_depth.to_i) {"term_context[#{term}]: #{term_context.inspect}"}
|
110
|
+
# log_debug("expand", depth: log_depth.to_i) {"term_context[#{term}]: #{term_context.inspect}"}
|
111
111
|
context = context.parse(term_context, base: @options[:base], propagate: false)
|
112
112
|
end
|
113
113
|
end
|
@@ -121,7 +121,7 @@ module JSON::LD
|
|
121
121
|
type_scoped_context: type_scoped_context,
|
122
122
|
log_depth: log_depth.to_i + 1)
|
123
123
|
|
124
|
-
log_debug("output object", depth: log_depth.to_i) {output_object.inspect}
|
124
|
+
# log_debug("output object", depth: log_depth.to_i) {output_object.inspect}
|
125
125
|
|
126
126
|
# If result contains the key @value:
|
127
127
|
if value?(output_object)
|
@@ -199,7 +199,7 @@ module JSON::LD
|
|
199
199
|
if (expanded_active_property || '@graph') == '@graph' &&
|
200
200
|
(output_object.key?('@value') || output_object.key?('@list') ||
|
201
201
|
(output_object.keys - KEY_ID).empty? && !framing)
|
202
|
-
log_debug(" =>", depth: log_depth.to_i) { "empty top-level: " + output_object.inspect}
|
202
|
+
# log_debug(" =>", depth: log_depth.to_i) { "empty top-level: " + output_object.inspect}
|
203
203
|
return nil
|
204
204
|
end
|
205
205
|
|
@@ -219,12 +219,12 @@ module JSON::LD
|
|
219
219
|
base: @options[:base],
|
220
220
|
override_protected: true)
|
221
221
|
end
|
222
|
-
log_debug("expand", depth: log_depth.to_i) {"property_scoped_context: #{context.inspect}"} unless property_scoped_context.nil?
|
222
|
+
# log_debug("expand", depth: log_depth.to_i) {"property_scoped_context: #{context.inspect}"} unless property_scoped_context.nil?
|
223
223
|
|
224
224
|
context.expand_value(active_property, input, base: @options[:base])
|
225
225
|
end
|
226
226
|
|
227
|
-
log_debug(depth: log_depth.to_i) {" => #{result.inspect}"}
|
227
|
+
# log_debug(depth: log_depth.to_i) {" => #{result.inspect}"}
|
228
228
|
result
|
229
229
|
end
|
230
230
|
|
@@ -258,10 +258,10 @@ module JSON::LD
|
|
258
258
|
expanded_property.to_s.start_with?("_:") &&
|
259
259
|
context.processingMode('json-ld-1.1')
|
260
260
|
|
261
|
-
log_debug("expand property", depth: log_depth.to_i) {"ap: #{active_property.inspect}, expanded: #{expanded_property.inspect}, value: #{value.inspect}"}
|
261
|
+
# log_debug("expand property", depth: log_depth.to_i) {"ap: #{active_property.inspect}, expanded: #{expanded_property.inspect}, value: #{value.inspect}"}
|
262
262
|
|
263
263
|
if expanded_property.nil?
|
264
|
-
log_debug(" => ", depth: log_depth.to_i) {"skip nil property"}
|
264
|
+
# log_debug(" => ", depth: log_depth.to_i) {"skip nil property"}
|
265
265
|
next
|
266
266
|
end
|
267
267
|
|
@@ -341,7 +341,7 @@ module JSON::LD
|
|
341
341
|
Array(output_object['@included']) + included_result
|
342
342
|
when '@type'
|
343
343
|
# If expanded property is @type and value is neither a string nor an array of strings, an invalid type value error has been detected and processing is aborted. Otherwise, set expanded value to the result of using the IRI Expansion algorithm, passing active context, true for vocab, and true for document relative to expand the value or each of its items.
|
344
|
-
log_debug("@type", depth: log_depth.to_i) {"value: #{value.inspect}"}
|
344
|
+
# log_debug("@type", depth: log_depth.to_i) {"value: #{value.inspect}"}
|
345
345
|
e_type = case value
|
346
346
|
when Array
|
347
347
|
value.map do |v|
|
@@ -516,7 +516,7 @@ module JSON::LD
|
|
516
516
|
|
517
517
|
# If expanded value contains an @reverse member, i.e., properties that are reversed twice, execute for each of its property and item the following steps:
|
518
518
|
if value.key?('@reverse')
|
519
|
-
log_debug("@reverse", depth: log_depth.to_i) {"double reverse: #{value.inspect}"}
|
519
|
+
# log_debug("@reverse", depth: log_depth.to_i) {"double reverse: #{value.inspect}"}
|
520
520
|
value['@reverse'].each do |property, item|
|
521
521
|
# If result does not have a property member, create one and set its value to an empty array.
|
522
522
|
# Append item to the value of the property member of result.
|
@@ -566,7 +566,7 @@ module JSON::LD
|
|
566
566
|
end
|
567
567
|
|
568
568
|
# Unless expanded value is null, set the expanded property member of result to expanded value.
|
569
|
-
log_debug("expand #{expanded_property}", depth: log_depth.to_i) { expanded_value.inspect}
|
569
|
+
# log_debug("expand #{expanded_property}", depth: log_depth.to_i) { expanded_value.inspect}
|
570
570
|
output_object[expanded_property] = expanded_value unless expanded_value.nil? && expanded_property == '@value' && input_type != '@json'
|
571
571
|
next
|
572
572
|
end
|
@@ -619,7 +619,7 @@ module JSON::LD
|
|
619
619
|
if id_context.nil?
|
620
620
|
context
|
621
621
|
else
|
622
|
-
log_debug("expand", depth: log_depth.to_i) {"id_context: #{id_context.inspect}"}
|
622
|
+
# log_debug("expand", depth: log_depth.to_i) {"id_context: #{id_context.inspect}"}
|
623
623
|
context.parse(id_context, base: @options[:base], propagate: false)
|
624
624
|
end
|
625
625
|
else
|
@@ -632,7 +632,7 @@ module JSON::LD
|
|
632
632
|
# If container mapping in the active context includes @type, and k is a term in the active context having a local context, use that context when expanding values
|
633
633
|
map_context = container_context.term_definitions[k].context if container.include?('@type') && container_context.term_definitions[k]
|
634
634
|
unless map_context.nil?
|
635
|
-
log_debug("expand", depth: log_depth.to_i) {"map_context: #{map_context.inspect}"}
|
635
|
+
# log_debug("expand", depth: log_depth.to_i) {"map_context: #{map_context.inspect}"}
|
636
636
|
map_context = container_context.parse(map_context, base: @options[:base],
|
637
637
|
propagate: false)
|
638
638
|
end
|
@@ -688,21 +688,21 @@ module JSON::LD
|
|
688
688
|
|
689
689
|
# If expanded value is null, ignore key by continuing to the next key from element.
|
690
690
|
if expanded_value.nil?
|
691
|
-
log_debug(" => skip nil value", depth: log_depth.to_i)
|
691
|
+
# log_debug(" => skip nil value", depth: log_depth.to_i)
|
692
692
|
next
|
693
693
|
end
|
694
|
-
log_debug(depth: log_depth.to_i) {" => #{expanded_value.inspect}"}
|
694
|
+
# log_debug(depth: log_depth.to_i) {" => #{expanded_value.inspect}"}
|
695
695
|
|
696
696
|
# If the container mapping associated to key in active context is @list and expanded value is not already a list object, convert expanded value to a list object by first setting it to an array containing only expanded value if it is not already an array, and then by setting it to a JSON object containing the key-value pair @list-expanded value.
|
697
697
|
if container.first == '@list' && container.length == 1 && !list?(expanded_value)
|
698
|
-
log_debug(" => ", depth: log_depth.to_i) { "convert #{expanded_value.inspect} to list"}
|
698
|
+
# log_debug(" => ", depth: log_depth.to_i) { "convert #{expanded_value.inspect} to list"}
|
699
699
|
expanded_value = {'@list' => as_array(expanded_value)}
|
700
700
|
end
|
701
|
-
log_debug(depth: log_depth.to_i) {" => #{expanded_value.inspect}"}
|
701
|
+
# log_debug(depth: log_depth.to_i) {" => #{expanded_value.inspect}"}
|
702
702
|
|
703
703
|
# convert expanded value to @graph if container specifies it
|
704
704
|
if container.first == '@graph' && container.length == 1
|
705
|
-
log_debug(" => ", depth: log_depth.to_i) { "convert #{expanded_value.inspect} to list"}
|
705
|
+
# log_debug(" => ", depth: log_depth.to_i) { "convert #{expanded_value.inspect} to list"}
|
706
706
|
expanded_value = as_array(expanded_value).map do |v|
|
707
707
|
{'@graph' => as_array(v)}
|
708
708
|
end
|
@@ -742,7 +742,7 @@ module JSON::LD
|
|
742
742
|
nest_context = if nest_context.nil?
|
743
743
|
context
|
744
744
|
else
|
745
|
-
log_debug("expand", depth: log_depth.to_i) {"nest_context: #{nest_context.inspect}"}
|
745
|
+
# log_debug("expand", depth: log_depth.to_i) {"nest_context: #{nest_context.inspect}"}
|
746
746
|
context.parse(nest_context, base: @options[:base],
|
747
747
|
override_protected: true)
|
748
748
|
end
|
data/lib/json/ld/from_rdf.rb
CHANGED
@@ -14,9 +14,11 @@ module JSON::LD
|
|
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
|
+
# @param extendedRepresentation (false)
|
18
|
+
# Use the extended internal representation for native types.
|
17
19
|
#
|
18
20
|
# @return [Array<Hash>] the JSON-LD document in normalized form
|
19
|
-
def from_statements(dataset, useRdfType: false, useNativeTypes: false)
|
21
|
+
def from_statements(dataset, useRdfType: false, useNativeTypes: false, extendedRepresentation: false)
|
20
22
|
default_graph = {}
|
21
23
|
graph_map = {'@default' => default_graph}
|
22
24
|
referenced_once = {}
|
@@ -30,7 +32,7 @@ module JSON::LD
|
|
30
32
|
|
31
33
|
# For each statement in dataset
|
32
34
|
dataset.each do |statement|
|
33
|
-
#log_debug("statement") { statement.to_nquads.chomp}
|
35
|
+
# log_debug("statement") { statement.to_nquads.chomp}
|
34
36
|
|
35
37
|
name = statement.graph_name ? @context.expand_iri(statement.graph_name, base: @options[:base]).to_s : '@default'
|
36
38
|
|
@@ -41,9 +43,9 @@ module JSON::LD
|
|
41
43
|
default_graph[name] ||= {'@id' => name} unless name == '@default'
|
42
44
|
|
43
45
|
subject = statement.subject.statement? ?
|
44
|
-
resource_representation(statement.subject, useNativeTypes)['@id'].to_json_c14n :
|
46
|
+
resource_representation(statement.subject, useNativeTypes, extendedRepresentation)['@id'].to_json_c14n :
|
45
47
|
statement.subject.to_s
|
46
|
-
node = node_map[subject] ||= resource_representation(statement.subject, useNativeTypes)
|
48
|
+
node = node_map[subject] ||= resource_representation(statement.subject, useNativeTypes, extendedRepresentation)
|
47
49
|
|
48
50
|
# If predicate is rdf:datatype, note subject in compound literal subjects map
|
49
51
|
if @options[:rdfDirection] == 'compound-literal' && statement.predicate == RDF.to_uri + 'direction'
|
@@ -53,10 +55,10 @@ module JSON::LD
|
|
53
55
|
# If object is an IRI, blank node identifier, or statement, and node map does not have an object member, create one and initialize its value to a new JSON object consisting of a single member @id whose value is set to object.
|
54
56
|
unless statement.object.literal?
|
55
57
|
object = statement.object.statement? ?
|
56
|
-
resource_representation(statement.object, useNativeTypes)['@id'].to_json_c14n :
|
58
|
+
resource_representation(statement.object, useNativeTypes, extendedRepresentation)['@id'].to_json_c14n :
|
57
59
|
statement.object.to_s
|
58
60
|
node_map[object] ||=
|
59
|
-
resource_representation(statement.object, useNativeTypes)
|
61
|
+
resource_representation(statement.object, useNativeTypes, extendedRepresentation)
|
60
62
|
end
|
61
63
|
|
62
64
|
# If predicate equals rdf:type, and object is an IRI or blank node identifier, append object to the value of the @type member of node. If no such member exists, create one and initialize it to an array whose only item is object. Finally, continue to the next RDF triple.
|
@@ -66,7 +68,7 @@ module JSON::LD
|
|
66
68
|
end
|
67
69
|
|
68
70
|
# Set value to the result of using the RDF to Object Conversion algorithm, passing object, rdfDirection, and use native types.
|
69
|
-
value = resource_representation(statement.object, useNativeTypes)
|
71
|
+
value = resource_representation(statement.object, useNativeTypes, extendedRepresentation)
|
70
72
|
|
71
73
|
merge_value(node, statement.predicate.to_s, value)
|
72
74
|
|
@@ -124,7 +126,7 @@ module JSON::LD
|
|
124
126
|
list, list_nodes = [], []
|
125
127
|
|
126
128
|
# 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:
|
127
|
-
#log_debug("list element?") {node.to_json(JSON_STATE) rescue 'malformed json'}
|
129
|
+
# log_debug("list element?") {node.to_json(JSON_STATE) rescue 'malformed json'}
|
128
130
|
while property == RDF.rest.to_s &&
|
129
131
|
blank_node?(node) &&
|
130
132
|
referenced_once[node['@id']] &&
|
@@ -163,31 +165,68 @@ module JSON::LD
|
|
163
165
|
node.delete(:usages)
|
164
166
|
result << node unless node_reference?(node)
|
165
167
|
end
|
166
|
-
#log_debug("fromRdf") {result.to_json(JSON_STATE) rescue 'malformed json'}
|
168
|
+
# log_debug("fromRdf") {result.to_json(JSON_STATE) rescue 'malformed json'}
|
167
169
|
result
|
168
170
|
end
|
169
171
|
|
170
172
|
private
|
171
|
-
|
173
|
+
|
174
|
+
RDF_LITERAL_NATIVE_TYPES = Set.new([RDF::XSD.boolean, RDF::XSD.integer, RDF::XSD.double]).freeze
|
175
|
+
|
176
|
+
def resource_representation(resource, useNativeTypes, extendedRepresentation)
|
172
177
|
case resource
|
173
178
|
when RDF::Statement
|
174
179
|
# Note, if either subject or object are a BNode which is used elsewhere,
|
175
180
|
# this might not work will with the BNode accounting from above.
|
176
|
-
rep = {'@id' => resource_representation(resource.subject, false)}
|
181
|
+
rep = {'@id' => resource_representation(resource.subject, false, extendedRepresentation)}
|
177
182
|
if resource.predicate == RDF.type
|
178
183
|
rep['@id'].merge!('@type' => resource.object.to_s)
|
179
184
|
else
|
180
185
|
rep['@id'].merge!(
|
181
186
|
resource.predicate.to_s =>
|
182
|
-
as_array(resource_representation(resource.object, useNativeTypes)))
|
187
|
+
as_array(resource_representation(resource.object, useNativeTypes, extendedRepresentation)))
|
183
188
|
end
|
184
189
|
rep
|
185
190
|
when RDF::Literal
|
186
|
-
@
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
+
base = @options[:base]
|
192
|
+
rdfDirection = @options[:rdfDirection]
|
193
|
+
res = {}
|
194
|
+
|
195
|
+
if resource.datatype == RDF::URI(RDF.to_uri + "JSON") && @context.processingMode('json-ld-1.1')
|
196
|
+
res['@type'] = '@json'
|
197
|
+
res['@value'] = begin
|
198
|
+
::JSON.parse(resource.object)
|
199
|
+
rescue ::JSON::ParserError => e
|
200
|
+
raise JSON::LD::JsonLdError::InvalidJsonLiteral, e.message
|
201
|
+
end
|
202
|
+
elsif useNativeTypes && extendedRepresentation
|
203
|
+
res['@value'] = resource # Raw literal
|
204
|
+
elsif resource.datatype.start_with?("https://www.w3.org/ns/i18n#") && rdfDirection == 'i18n-datatype' && @context.processingMode('json-ld-1.1')
|
205
|
+
lang, dir = resource.datatype.fragment.split('_')
|
206
|
+
res['@value'] = resource.to_s
|
207
|
+
unless lang.empty?
|
208
|
+
if lang !~ /^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$/
|
209
|
+
if options[:validate]
|
210
|
+
raise JsonLdError::InvalidLanguageMapping, "rdf:language must be valid BCP47: #{lang.inspect}"
|
211
|
+
else
|
212
|
+
warn "rdf:language must be valid BCP47: #{lang.inspect}"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
res['@language'] = lang
|
216
|
+
end
|
217
|
+
res['@direction'] = dir
|
218
|
+
elsif useNativeTypes && RDF_LITERAL_NATIVE_TYPES.include?(resource.datatype) && resource.valid?
|
219
|
+
res['@value'] = resource.object
|
220
|
+
else
|
221
|
+
resource.canonicalize! if resource.valid? && resource.datatype == RDF::XSD.double
|
222
|
+
if resource.datatype?
|
223
|
+
res['@type'] = resource.datatype.to_s
|
224
|
+
elsif resource.language?
|
225
|
+
res['@language'] = resource.language.to_s
|
226
|
+
end
|
227
|
+
res['@value'] = resource.to_s
|
228
|
+
end
|
229
|
+
res
|
191
230
|
else
|
192
231
|
{'@id' => resource.to_s}
|
193
232
|
end
|
@@ -19,7 +19,7 @@ module JSON::LD
|
|
19
19
|
else Context.parse(@options[:context])
|
20
20
|
end
|
21
21
|
|
22
|
-
#log_debug("prologue") {"context: #{context.inspect}"}
|
22
|
+
# log_debug("prologue") {"context: #{context.inspect}"}
|
23
23
|
if context
|
24
24
|
@output.puts %({"@context": #{context.serialize['@context'].to_json}, "@graph": [)
|
25
25
|
else
|
@@ -39,7 +39,7 @@ module JSON::LD
|
|
39
39
|
#
|
40
40
|
# @return [void] `self`
|
41
41
|
def stream_statement(statement)
|
42
|
-
#log_debug("ss") {"state: #{@state.inspect}, stmt: #{statement}"}
|
42
|
+
# log_debug("ss") {"state: #{@state.inspect}, stmt: #{statement}"}
|
43
43
|
if @current_graph != statement.graph_name
|
44
44
|
end_graph
|
45
45
|
start_graph(statement.graph_name)
|
@@ -76,7 +76,7 @@ module JSON::LD
|
|
76
76
|
# Complete open statements
|
77
77
|
# @return [void] `self`
|
78
78
|
def stream_epilogue
|
79
|
-
#log_debug("epilogue") {"state: #{@state.inspect}"}
|
79
|
+
# log_debug("epilogue") {"state: #{@state.inspect}"}
|
80
80
|
end_graph
|
81
81
|
if context
|
82
82
|
@output.puts "\n]}"
|
@@ -89,7 +89,7 @@ module JSON::LD
|
|
89
89
|
private
|
90
90
|
|
91
91
|
def start_graph(resource)
|
92
|
-
#log_debug("start_graph") {"state: #{@state.inspect}, resource: #{resource}"}
|
92
|
+
# log_debug("start_graph") {"state: #{@state.inspect}, resource: #{resource}"}
|
93
93
|
if resource
|
94
94
|
@output.puts(",") if %i(wrote_node wrote_graph).include?(@state)
|
95
95
|
@output.puts %({"@id": "#{resource}", "@graph": [)
|
@@ -99,7 +99,7 @@ module JSON::LD
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def end_graph
|
102
|
-
#log_debug("end_graph") {"state: #{@state.inspect}, ctx: #{@current_graph}"}
|
102
|
+
# log_debug("end_graph") {"state: #{@state.inspect}, ctx: #{@current_graph}"}
|
103
103
|
end_node
|
104
104
|
if @current_graph
|
105
105
|
@output.write %(]})
|
@@ -108,7 +108,7 @@ module JSON::LD
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def end_node
|
111
|
-
#log_debug("end_node") {"state: #{@state.inspect}, node: #{@current_node_def.to_json}"}
|
111
|
+
# log_debug("end_node") {"state: #{@state.inspect}, node: #{@current_node_def.to_json}"}
|
112
112
|
@output.puts(",") if %i(wrote_node wrote_graph).include?(@state)
|
113
113
|
if @current_node_def
|
114
114
|
node_def = if context
|
data/lib/json/ld/to_rdf.rb
CHANGED
@@ -25,6 +25,8 @@ module JSON::LD
|
|
25
25
|
datatype = RDF::URI(RDF.to_uri + "JSON") if datatype == '@json'
|
26
26
|
|
27
27
|
case value
|
28
|
+
when RDF::Value
|
29
|
+
return value
|
28
30
|
when TrueClass, FalseClass
|
29
31
|
# If value is true or false, then set value its canonical lexical form as defined in the section Data Round Tripping. If datatype is null, set it to xsd:boolean.
|
30
32
|
value = value.to_s
|
@@ -88,14 +90,14 @@ module JSON::LD
|
|
88
90
|
to_enum(:item_to_rdf, item['@id'], quoted: true).to_a.first
|
89
91
|
end
|
90
92
|
|
91
|
-
#log_debug("item_to_rdf") {"subject: #{subject.to_ntriples rescue 'malformed rdf'}"}
|
93
|
+
# log_debug("item_to_rdf") {"subject: #{subject.to_ntriples rescue 'malformed rdf'}"}
|
92
94
|
item.each do |property, values|
|
93
95
|
case property
|
94
96
|
when '@type'
|
95
97
|
# If property is @type, construct triple as an RDF Triple composed of id, rdf:type, and object from values where id and object are represented either as IRIs or Blank Nodes
|
96
98
|
values.each do |v|
|
97
99
|
object = as_resource(v)
|
98
|
-
#log_debug("item_to_rdf") {"type: #{object.to_ntriples rescue 'malformed rdf'}"}
|
100
|
+
# log_debug("item_to_rdf") {"type: #{object.to_ntriples rescue 'malformed rdf'}"}
|
99
101
|
yield RDF::Statement(subject, RDF.type, object, graph_name: graph_name, quoted: quoted)
|
100
102
|
end
|
101
103
|
when '@graph'
|
@@ -107,12 +109,12 @@ module JSON::LD
|
|
107
109
|
raise "Huh?" unless values.is_a?(Hash)
|
108
110
|
values.each do |prop, vv|
|
109
111
|
predicate = as_resource(prop)
|
110
|
-
#log_debug("item_to_rdf") {"@reverse predicate: #{predicate.to_ntriples rescue 'malformed rdf'}"}
|
112
|
+
# log_debug("item_to_rdf") {"@reverse predicate: #{predicate.to_ntriples rescue 'malformed rdf'}"}
|
111
113
|
# For each item in values
|
112
114
|
vv.each do |v|
|
113
115
|
# Item is a node definition. Generate object as the result of the Object Converstion algorithm passing item.
|
114
116
|
object = item_to_rdf(v, graph_name: graph_name, &block)
|
115
|
-
#log_debug("item_to_rdf") {"subject: #{object.to_ntriples rescue 'malformed rdf'}"}
|
117
|
+
# log_debug("item_to_rdf") {"subject: #{object.to_ntriples rescue 'malformed rdf'}"}
|
116
118
|
# yield subject, prediate, and literal to results.
|
117
119
|
yield RDF::Statement(object, predicate, subject, graph_name: graph_name, quoted: quoted)
|
118
120
|
end
|
@@ -127,12 +129,12 @@ module JSON::LD
|
|
127
129
|
# Otherwise, property is an IRI or Blank Node identifier
|
128
130
|
# Initialize predicate from property as an IRI or Blank node
|
129
131
|
predicate = as_resource(property)
|
130
|
-
#log_debug("item_to_rdf") {"predicate: #{predicate.to_ntriples rescue 'malformed rdf'}"}
|
132
|
+
# log_debug("item_to_rdf") {"predicate: #{predicate.to_ntriples rescue 'malformed rdf'}"}
|
131
133
|
|
132
134
|
# For each item in values
|
133
135
|
values.each do |v|
|
134
136
|
if list?(v)
|
135
|
-
#log_debug("item_to_rdf") {"list: #{v.inspect}"}
|
137
|
+
# log_debug("item_to_rdf") {"list: #{v.inspect}"}
|
136
138
|
# 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.
|
137
139
|
object = parse_list(v['@list'], graph_name: graph_name, &block)
|
138
140
|
|
@@ -141,7 +143,7 @@ module JSON::LD
|
|
141
143
|
else
|
142
144
|
# Otherwise, item is a value object or a node definition. Generate object as the result of the Object Converstion algorithm passing item.
|
143
145
|
object = item_to_rdf(v, graph_name: graph_name, &block)
|
144
|
-
#log_debug("item_to_rdf") {"object: #{object.to_ntriples rescue 'malformed rdf'}"}
|
146
|
+
# log_debug("item_to_rdf") {"object: #{object.to_ntriples rescue 'malformed rdf'}"}
|
145
147
|
# yield subject, prediate, and literal to results.
|
146
148
|
yield RDF::Statement(subject, predicate, object, graph_name: graph_name, quoted: quoted)
|
147
149
|
end
|
@@ -162,7 +164,7 @@ module JSON::LD
|
|
162
164
|
# @return [Array<RDF::Statement>]
|
163
165
|
# Statements for each item in the list
|
164
166
|
def parse_list(list, graph_name: nil, &block)
|
165
|
-
#log_debug('parse_list') {"list: #{list.inspect}"}
|
167
|
+
# log_debug('parse_list') {"list: #{list.inspect}"}
|
166
168
|
|
167
169
|
last = list.pop
|
168
170
|
result = first_bnode = last ? node : RDF.nil
|
data/lib/json/ld/writer.rb
CHANGED
@@ -298,7 +298,7 @@ module JSON::LD
|
|
298
298
|
stream_epilogue
|
299
299
|
else
|
300
300
|
|
301
|
-
log_debug("writer") { "serialize #{@repo.count} statements, #{@options.inspect}"}
|
301
|
+
# log_debug("writer") { "serialize #{@repo.count} statements, #{@options.inspect}"}
|
302
302
|
result = API.fromRdf(@repo, **@options.merge(serializer: nil))
|
303
303
|
|
304
304
|
# Some options may be indicated from accept parameters
|
@@ -326,11 +326,11 @@ module JSON::LD
|
|
326
326
|
|
327
327
|
if frame = @options[:frame]
|
328
328
|
# Perform framing, if given a frame
|
329
|
-
log_debug("writer") { "frame result"}
|
329
|
+
# log_debug("writer") { "frame result"}
|
330
330
|
result = API.frame(result, frame, **@options.merge(serializer: nil))
|
331
331
|
elsif context
|
332
332
|
# Perform compaction, if we have a context
|
333
|
-
log_debug("writer") { "compact result"}
|
333
|
+
# log_debug("writer") { "compact result"}
|
334
334
|
result = API.compact(result, context, **@options.merge(serializer: nil))
|
335
335
|
end
|
336
336
|
|
data/spec/context_spec.rb
CHANGED
@@ -655,7 +655,6 @@ describe JSON::LD::Context do
|
|
655
655
|
"@language" => "en"
|
656
656
|
}
|
657
657
|
}, logger)
|
658
|
-
expect(subject.to_rb).not_to be_empty
|
659
658
|
end
|
660
659
|
|
661
660
|
it "@vocab" do
|
@@ -665,7 +664,6 @@ describe JSON::LD::Context do
|
|
665
664
|
"@vocab" => "http://example.com/"
|
666
665
|
}
|
667
666
|
}, logger)
|
668
|
-
expect(subject.to_rb).not_to be_empty
|
669
667
|
end
|
670
668
|
|
671
669
|
it "term mappings" do
|
@@ -676,7 +674,6 @@ describe JSON::LD::Context do
|
|
676
674
|
"foo" => "http://example.com/"
|
677
675
|
}
|
678
676
|
}, logger)
|
679
|
-
expect(c.to_rb).not_to be_empty
|
680
677
|
end
|
681
678
|
|
682
679
|
it "@context" do
|
@@ -931,6 +928,37 @@ describe JSON::LD::Context do
|
|
931
928
|
|
932
929
|
end
|
933
930
|
|
931
|
+
describe "#to_rb" do
|
932
|
+
before(:all) {JSON::LD::Context.instance_variable_set(:@cache, nil)}
|
933
|
+
subject {
|
934
|
+
allow(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
|
935
|
+
context.parse("http://example.com/context")
|
936
|
+
}
|
937
|
+
|
938
|
+
it "encodes as utf-8" do
|
939
|
+
expect(subject.to_rb).to match(/encoding: utf-8/)
|
940
|
+
end
|
941
|
+
|
942
|
+
it "marked as auto-generated" do
|
943
|
+
expect(subject.to_rb).to match(/This file generated automatically from/)
|
944
|
+
end
|
945
|
+
|
946
|
+
it "includes URL in preloaded" do
|
947
|
+
expect(subject.to_rb).to include(%(add_preloaded("http://example.com/context")))
|
948
|
+
end
|
949
|
+
|
950
|
+
it "includes processingMode" do
|
951
|
+
expect(subject.to_rb).to include(%(processingMode: "json-ld-1.1"))
|
952
|
+
end
|
953
|
+
|
954
|
+
it "term mappings" do
|
955
|
+
expect(subject.to_rb).to include(%("avatar" => TermDefinition.new("avatar", id: "http://xmlns.com/foaf/0.1/avatar", type_mapping: "@id")))
|
956
|
+
expect(subject.to_rb).to include(%("homepage" => TermDefinition.new("homepage", id: "http://xmlns.com/foaf/0.1/homepage", type_mapping: "@id")))
|
957
|
+
expect(subject.to_rb).to include(%("name" => TermDefinition.new("name", id: "http://xmlns.com/foaf/0.1/name", simple: true)))
|
958
|
+
expect(subject.to_rb).to include(%("xsd" => TermDefinition.new("xsd", id: "http://www.w3.org/2001/XMLSchema#", simple: true, prefix: true)))
|
959
|
+
end
|
960
|
+
end
|
961
|
+
|
934
962
|
describe "#base=" do
|
935
963
|
subject {
|
936
964
|
context.parse({
|
@@ -1553,14 +1581,6 @@ describe JSON::LD::Context do
|
|
1553
1581
|
"native double" => ["foo", 1.1e1, {"@value" => 1.1E1}],
|
1554
1582
|
"native date" => ["foo", Date.parse("2011-12-27"), {"@value" => "2011-12-27", "@type" => RDF::XSD.date.to_s}],
|
1555
1583
|
"native dateTime" =>["foo", DateTime.parse("2011-12-27T10:11:12Z"), {"@value" => "2011-12-27T10:11:12Z", "@type" => RDF::XSD.dateTime.to_s}],
|
1556
|
-
"rdf boolean" => ["foo", RDF::Literal(true), {"@value" => "true", "@type" => RDF::XSD.boolean.to_s}],
|
1557
|
-
"rdf integer" => ["foo", RDF::Literal(1), {"@value" => "1", "@type" => RDF::XSD.integer.to_s}],
|
1558
|
-
"rdf decimal" => ["foo", RDF::Literal::Decimal.new(1.1), {"@value" => "1.1", "@type" => RDF::XSD.decimal.to_s}],
|
1559
|
-
"rdf double" => ["foo", RDF::Literal::Double.new(1.1), {"@value" => "1.1E0", "@type" => RDF::XSD.double.to_s}],
|
1560
|
-
"rdf URI" => ["foo", RDF::URI("foo"), {"@id" => "foo"}],
|
1561
|
-
"rdf date " => ["foo", RDF::Literal(Date.parse("2011-12-27")), {"@value" => "2011-12-27", "@type" => RDF::XSD.date.to_s}],
|
1562
|
-
"rdf nonNeg" => ["foo", RDF::Literal::NonNegativeInteger.new(1), {"@value" => "1", "@type" => RDF::XSD.nonNegativeInteger}],
|
1563
|
-
"rdf float" => ["foo", RDF::Literal::Float.new(1.0), {"@value" => "1.0", "@type" => RDF::XSD.float}],
|
1564
1584
|
"ex:none string" => ["ex:none", "foo", {"@value" => "foo"}],
|
1565
1585
|
"ex:none boolean" =>["ex:none", true, {"@value" => true}],
|
1566
1586
|
"ex:none integer" =>["ex:none", 1, {"@value" => 1}],
|
data/spec/frame_spec.rb
CHANGED
@@ -2463,6 +2463,49 @@ describe JSON::LD::API do
|
|
2463
2463
|
}),
|
2464
2464
|
processingMode: "json-ld-1.1"
|
2465
2465
|
},
|
2466
|
+
"issue #142": {
|
2467
|
+
input: %({
|
2468
|
+
"@context":{
|
2469
|
+
"ex":"http://example.org/vocab#",
|
2470
|
+
"ex:info":{"@type":"@json"},
|
2471
|
+
"ex:other":{"@type":"@json"}
|
2472
|
+
},
|
2473
|
+
"@id":"http://example.org/test/#library",
|
2474
|
+
"@type":"ex:Library",
|
2475
|
+
"ex:info":{
|
2476
|
+
"author":"JOHN",
|
2477
|
+
"pages":200
|
2478
|
+
},
|
2479
|
+
"ex:other":{
|
2480
|
+
"publisher":"JANE"
|
2481
|
+
}
|
2482
|
+
}),
|
2483
|
+
frame: %({
|
2484
|
+
"@context":{
|
2485
|
+
"ex":"http://example.org/vocab#",
|
2486
|
+
"ex:info":{"@type":"@json"},
|
2487
|
+
"ex:other":{"@type":"@json"}
|
2488
|
+
},
|
2489
|
+
"http://example.org/vocab#info":{}
|
2490
|
+
}),
|
2491
|
+
output: %({
|
2492
|
+
"@context": {
|
2493
|
+
"ex": "http://example.org/vocab#",
|
2494
|
+
"ex:info": {"@type": "@json"},
|
2495
|
+
"ex:other": {"@type": "@json"}
|
2496
|
+
},
|
2497
|
+
"@id": "http://example.org/test/#library",
|
2498
|
+
"@type": "ex:Library",
|
2499
|
+
"ex:info": {
|
2500
|
+
"author": "JOHN",
|
2501
|
+
"pages": 200
|
2502
|
+
},
|
2503
|
+
"ex:other": {
|
2504
|
+
"publisher": "JANE"
|
2505
|
+
}
|
2506
|
+
}),
|
2507
|
+
processingMode: "json-ld-1.1"
|
2508
|
+
}
|
2466
2509
|
}.each do |title, params|
|
2467
2510
|
it title do
|
2468
2511
|
do_frame(params)
|