json-ld 0.3.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +2 -2
- data/VERSION +1 -1
- data/lib/json/ld.rb +10 -0
- data/lib/json/ld/api.rb +43 -26
- data/lib/json/ld/compact.rb +119 -17
- data/lib/json/ld/evaluation_context.rb +186 -146
- data/lib/json/ld/expand.rb +192 -86
- data/lib/json/ld/extensions.rb +18 -0
- data/lib/json/ld/flatten.rb +6 -8
- data/lib/json/ld/frame.rb +3 -3
- data/lib/json/ld/to_rdf.rb +4 -6
- data/lib/json/ld/utils.rb +46 -15
- data/spec/compact_spec.rb +130 -113
- data/spec/evaluation_context_spec.rb +230 -43
- data/spec/expand_spec.rb +185 -17
- data/spec/flatten_spec.rb +3 -5
- data/spec/frame_spec.rb +1 -1
- data/spec/suite_compact_spec.rb +4 -1
- data/spec/suite_expand_spec.rb +2 -4
- data/spec/suite_flatten_spec.rb +32 -0
- data/spec/suite_frame_spec.rb +1 -1
- data/spec/suite_helper.rb +0 -3
- data/spec/test-files/test-7-compacted.json +3 -3
- data/spec/test-files/test-7-expanded.json +3 -3
- data/spec/to_rdf_spec.rb +1 -1
- data/spec/writer_spec.rb +1 -1
- metadata +16 -30
data/lib/json/ld/expand.rb
CHANGED
@@ -47,117 +47,194 @@ module JSON::LD
|
|
47
47
|
depth do
|
48
48
|
output_object = Hash.ordered
|
49
49
|
# Then, proceed and process each property and value in element as follows:
|
50
|
-
input.each do |
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
50
|
+
input.keys.kw_sort.each do |property|
|
51
|
+
value = input[property]
|
52
|
+
expanded_property = context.expand_iri(property, :position => :predicate, :quiet => true, :namer => namer)
|
53
|
+
|
54
|
+
if expanded_property.is_a?(Array)
|
55
|
+
# If expanded property is an array, remove every element which is not a absolute IRI.
|
56
|
+
expanded_property = expanded_property.map {|p| p.to_s if p && p.uri? && p.absolute? || p.node?}.compact
|
57
|
+
expanded_property = nil if expanded_property.empty?
|
58
|
+
elsif expanded_property.is_a?(RDF::Resource)
|
59
|
+
expanded_property = expanded_property.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
debug("expand property") {"ap: #{active_property.inspect}, expanded: #{expanded_property.inspect}, value: #{value.inspect}"}
|
63
|
+
|
64
|
+
# If expanded property is an empty array, or null, continue with the next property from element
|
65
|
+
if expanded_property.nil?
|
66
|
+
debug(" => ") {"skip nil property"}
|
62
67
|
next
|
63
68
|
end
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
69
|
+
expanded_property
|
70
|
+
|
71
|
+
if expanded_property.is_a?(String) && expanded_property[0,1] == '@'
|
72
|
+
expanded_value = case expanded_property
|
73
|
+
when '@id'
|
74
|
+
# If expanded property is @id, value must be a string. Set the @id member in result to the result of expanding value according the IRI Expansion algorithm relative to the document base and re-labeling Blank Nodes.
|
75
|
+
context.expand_iri(value, :position => :subject, :quiet => true, :namer => namer).to_s
|
76
|
+
when '@type'
|
77
|
+
# If expanded property is @type, value must be a string or array of strings. Set the @type member of result to the result of expanding value according the IRI Expansion algorithm relative to the document base and re-labeling Blank Nodes, unless that result is an empty array.
|
78
|
+
debug("@type") {"value: #{value.inspect}"}
|
79
|
+
case value
|
80
|
+
when Array
|
81
|
+
depth do
|
82
|
+
[value].flatten.map do |v|
|
83
|
+
v = v['@id'] if node_reference?(v)
|
84
|
+
raise ProcessingError, "Object value must be a string or a node reference: #{v.inspect}" unless v.is_a?(String)
|
85
|
+
context.expand_iri(v, options.merge(:position => :subject, :quiet => true, :namer => namer)).to_s
|
86
|
+
end
|
87
|
+
end
|
88
|
+
when Hash
|
89
|
+
# Empty object used for @type wildcard or node reference
|
90
|
+
if node_reference?(value)
|
91
|
+
context.expand_iri(value['@id'], options.merge(:position => :property, :quiet => true, :namer => namer)).to_s
|
92
|
+
elsif !value.empty?
|
93
|
+
raise ProcessingError, "Object value of @type must be empty or a node reference: #{value.inspect}"
|
94
|
+
else
|
95
|
+
value
|
82
96
|
end
|
83
|
-
end
|
84
|
-
when Hash
|
85
|
-
# Empty object used for @type wildcard or node reference
|
86
|
-
if node_reference?(value)
|
87
|
-
context.expand_iri(value['@id'], options.merge(:position => :property, :quiet => true)).to_s
|
88
|
-
elsif !value.empty?
|
89
|
-
raise ProcessingError, "Object value of @type must be empty or a node reference: #{value.inspect}"
|
90
97
|
else
|
91
|
-
value
|
98
|
+
context.expand_iri(value, options.merge(:position => :property, :quiet => true, :namer => namer)).to_s
|
99
|
+
end
|
100
|
+
when '@value'
|
101
|
+
# If expanded property is @value, value must be a scalar or null. Set the @value member of result to value.
|
102
|
+
raise ProcessingError::Lossy, "Value of #{expanded_property} must be a string, was #{value.inspect}" if value.is_a?(Hash) || value.is_a?(Array)
|
103
|
+
value
|
104
|
+
when '@language'
|
105
|
+
# If expanded property is @language, value must be a string with the lexical form described in [BCP47] or null. Set the @language member of result to the lowercased value.
|
106
|
+
raise ProcessingError::Lossy, "Value of #{expanded_property} must be a string, was #{value.inspect}" if value.is_a?(Hash) || value.is_a?(Array)
|
107
|
+
value.to_s.downcase
|
108
|
+
when '@annotation'
|
109
|
+
# If expanded property is @annotation value must be a string. Set the @annotation member of result to value.
|
110
|
+
value = value.first if value.is_a?(Array) && value.length == 1
|
111
|
+
raise ProcessingError, "Value of @annotation is not a string: #{value.inspect}" unless value.is_a?(String)
|
112
|
+
value.to_s
|
113
|
+
when '@list', '@set', '@graph'
|
114
|
+
# If expanded property is @set, @list, or @graph, set the expanded property member of result to the result of expanding value by recursively using this algorithm, along with the active context and active property. If expanded property is @list and active property is null or @graph, pass @list as active property instead.
|
115
|
+
value = [value] unless value.is_a?(Array)
|
116
|
+
ap = expanded_property == '@list' && ((active_property || '@graph') == '@graph') ? '@list' : active_property
|
117
|
+
value = depth { expand(value, ap, context, options) }
|
118
|
+
|
119
|
+
# If expanded property is @list, and any expanded value
|
120
|
+
# is an object containing an @list property, throw an exception, as lists of lists are not supported
|
121
|
+
if expanded_property == '@list' && value.any? {|v| v.is_a?(Hash) && v.has_key?('@list')}
|
122
|
+
raise ProcessingError::ListOfLists, "A list may not contain another list"
|
92
123
|
end
|
124
|
+
|
125
|
+
value
|
93
126
|
else
|
94
|
-
|
127
|
+
# Skip unknown keyword
|
128
|
+
next
|
95
129
|
end
|
96
|
-
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
#
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
#
|
109
|
-
|
110
|
-
|
130
|
+
|
131
|
+
debug("expand #{expanded_property}") { expanded_value.inspect}
|
132
|
+
output_object[expanded_property] = expanded_value
|
133
|
+
next
|
134
|
+
end
|
135
|
+
|
136
|
+
expanded_value = if context.container(property) == '@language' && value.is_a?(Hash)
|
137
|
+
# Otherwise, if value is a JSON object and property is not a keyword and its associated term entry in the active context has a @container key associated with a value of @language, process the associated value as a language map:
|
138
|
+
|
139
|
+
# Set multilingual array to an empty array.
|
140
|
+
language_map_values = []
|
141
|
+
|
142
|
+
# For each key-value in the language map:
|
143
|
+
value.keys.sort.each do |k|
|
144
|
+
[value[k]].flatten.each do |v|
|
145
|
+
# Create a new JSON Object, referred to as an expanded language object.
|
146
|
+
expanded_language_object = Hash.new
|
147
|
+
|
148
|
+
# Add a key-value pair to the expanded language object where the key is @value and the value is the value associated with the key in the language map.
|
149
|
+
raise ProcessingError::LanguageMap, "Expected #{vv.inspect} to be a string" unless v.is_a?(String)
|
150
|
+
expanded_language_object['@value'] = v
|
151
|
+
|
152
|
+
# Add a key-value pair to the expanded language object where the key is @language, and the value is the key in the language map, transformed to lowercase.
|
153
|
+
# FIXME: check for BCP47 conformance
|
154
|
+
expanded_language_object['@language'] = k.downcase
|
155
|
+
# Append the expanded language object to the multilingual array.
|
156
|
+
language_map_values << expanded_language_object
|
157
|
+
end
|
111
158
|
end
|
159
|
+
# Set the value associated with property to the multilingual array.
|
160
|
+
language_map_values
|
161
|
+
elsif context.container(property) == '@annotation' && value.is_a?(Hash)
|
162
|
+
# Otherwise, if value is a JSON object and property is not a keyword and its associated term entry in the active context has a @container key associated with a value of @annotation, process the associated value as a annotation:
|
163
|
+
|
164
|
+
# Set ary to an empty array.
|
165
|
+
annotation_map_values = []
|
112
166
|
|
113
|
-
value
|
167
|
+
# For each key-value in the object:
|
168
|
+
value.keys.sort.each do |k|
|
169
|
+
[value[k]].flatten.each do |v|
|
170
|
+
# Expand the value, adding an '@annotation' key with value equal to the key
|
171
|
+
expanded_value = depth { expand(v, property, context, options) }
|
172
|
+
next unless expanded_value
|
173
|
+
expanded_value['@annotation'] ||= k
|
174
|
+
annotation_map_values << expanded_value
|
175
|
+
end
|
176
|
+
end
|
177
|
+
# Set the value associated with property to the multilingual array.
|
178
|
+
annotation_map_values
|
114
179
|
else
|
115
|
-
# Otherwise, expand value recursively using this algorithm, passing copies of the active context and active property.
|
116
|
-
depth { expand(value,
|
180
|
+
# Otherwise, expand value by recursively using this algorithm, passing copies of the active context and property as active property.
|
181
|
+
depth { expand(value, property, context, options) }
|
117
182
|
end
|
118
183
|
|
119
|
-
#
|
120
|
-
|
121
|
-
# from element.
|
122
|
-
if property != '@value' && expanded_value.nil?
|
184
|
+
# Continue to the next property-value pair from element if value is null.
|
185
|
+
if expanded_value.nil?
|
123
186
|
debug(" => skip nil value")
|
124
187
|
next
|
125
188
|
end
|
126
189
|
|
127
|
-
# If
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
(!expanded_value.is_a?(Hash) || !expanded_value.fetch('@list', false))
|
133
|
-
debug(" => ") { "convert #{expanded_value.inspect} to list"}
|
190
|
+
# If property's container mapping is set to @list and value is not a JSON object or is a JSON object without a @list member, replace value with a JSON object having a @list member whose value is set to value, ensuring that value is an array.
|
191
|
+
if context.container(property) == '@list' &&
|
192
|
+
(!expanded_value.is_a?(Hash) || !expanded_value.fetch('@list', false))
|
193
|
+
|
194
|
+
debug(" => ") { "convert #{expanded_value.inspect} to list"}
|
134
195
|
expanded_value = {'@list' => [expanded_value].flatten}
|
135
196
|
end
|
136
197
|
|
137
|
-
# Convert value to array form
|
138
|
-
|
139
|
-
|
140
|
-
expanded_value = [expanded_value]
|
141
|
-
end
|
198
|
+
# Convert value to array form
|
199
|
+
debug(" => ") {"expanded property: #{expanded_property.inspect}"}
|
200
|
+
expanded_value = [expanded_value] unless expanded_value.is_a?(Array)
|
142
201
|
|
143
|
-
if
|
144
|
-
|
145
|
-
|
202
|
+
if expanded_property.is_a?(Array)
|
203
|
+
label_blanknodes(expanded_value)
|
204
|
+
expanded_property.map(&:to_s).each do |prop|
|
205
|
+
# label all blank nodes in value with blank node identifiers by using the Label Blank Nodes Algorithm.
|
206
|
+
output_object[prop] ||= []
|
207
|
+
output_object[prop] += expanded_value.dup
|
208
|
+
end
|
146
209
|
else
|
147
|
-
|
148
|
-
|
210
|
+
if output_object.has_key?(expanded_property)
|
211
|
+
# If element already contains a expanded_property property, append value to the existing value.
|
212
|
+
output_object[expanded_property] += expanded_value
|
213
|
+
else
|
214
|
+
# Otherwise, create a property property with value as value.
|
215
|
+
output_object[expanded_property] = expanded_value
|
216
|
+
end
|
149
217
|
end
|
150
218
|
debug {" => #{expanded_value.inspect}"}
|
151
219
|
end
|
152
220
|
|
153
221
|
debug("output object") {output_object.inspect}
|
154
222
|
|
223
|
+
# If the active property is null or @graph and element has a @value member without an @annotation member, or element consists of only an @id member, set element to null.
|
224
|
+
debug("output object(ap)") {((active_property || '@graph') == '@graph').inspect}
|
225
|
+
if (active_property || '@graph') == '@graph' &&
|
226
|
+
((output_object.has_key?('@value') && !output_object.has_key?('@annotation')) ||
|
227
|
+
(output_object.keys - %w(@id)).empty?)
|
228
|
+
debug("empty top-level") {output_object.inspect}
|
229
|
+
return nil
|
230
|
+
end
|
231
|
+
|
155
232
|
# If the processed element has an @value property
|
156
233
|
if output_object.has_key?('@value')
|
157
234
|
output_object.delete('@language') if output_object['@language'].to_s.empty?
|
158
235
|
output_object.delete('@type') if output_object['@type'].to_s.empty?
|
159
|
-
if
|
160
|
-
raise ProcessingError, "element must not have more than one other property, which can either be @language or @type with a string value." unless value.is_a?(String)
|
236
|
+
if (%w(@annotation @language @type) - output_object.keys).empty?
|
237
|
+
raise ProcessingError, "element must not have more than one other property other than @annotation, which can either be @language or @type with a string value." unless value.is_a?(String)
|
161
238
|
end
|
162
239
|
|
163
240
|
# if the value of @value equals null, replace element with the value of null.
|
@@ -168,24 +245,53 @@ module JSON::LD
|
|
168
245
|
output_object['@type'] = [output_object['@type']]
|
169
246
|
end
|
170
247
|
|
171
|
-
# If element has an @set or @list property, it must be the only property. Set element to the value of @set;
|
248
|
+
# If element has an @set or @list property, it must be the only property (other tha @annotation). Set element to the value of @set;
|
172
249
|
# leave @list untouched.
|
173
250
|
if !(%w(@set @list) & output_object.keys).empty?
|
174
|
-
|
251
|
+
o_keys = output_object.keys - %w(@set @list @annotation)
|
252
|
+
raise ProcessingError, "element must have only @set or @list: #{output_object.keys.inspect}" if o_keys.length > 1
|
175
253
|
|
176
254
|
output_object = output_object.values.first unless output_object.has_key?('@list')
|
177
255
|
end
|
178
256
|
|
179
|
-
#
|
180
|
-
|
257
|
+
# Re-order result keys
|
258
|
+
if output_object.is_a?(Hash) && output_object.keys == %w(@language)
|
259
|
+
# If element has just a @language property, set element to null.
|
260
|
+
nil
|
261
|
+
elsif output_object.is_a?(Hash)
|
262
|
+
r = Hash.ordered
|
263
|
+
output_object.keys.kw_sort.each {|k| r[k] = output_object[k]}
|
264
|
+
r
|
265
|
+
else
|
266
|
+
output_object
|
267
|
+
end
|
181
268
|
end
|
182
269
|
else
|
183
270
|
# Otherwise, unless the value is a number, expand the value according to the Value Expansion rules, passing active property.
|
184
|
-
context.expand_value(active_property, input,
|
271
|
+
context.expand_value(active_property, input,
|
272
|
+
:position => :subject, :namer => namer, :depth => @depth
|
273
|
+
) unless input.nil? || active_property.nil? || active_property == '@graph'
|
185
274
|
end
|
186
275
|
|
187
276
|
debug {" => #{result.inspect}"}
|
188
277
|
result
|
189
278
|
end
|
279
|
+
|
280
|
+
protected
|
281
|
+
# @param [Array, Hash] input
|
282
|
+
def label_blanknodes(element)
|
283
|
+
if element.is_a?(Array)
|
284
|
+
element.each {|e| label_blanknodes(e)}
|
285
|
+
elsif list?(element)
|
286
|
+
element['@list'].each {|e| label_blanknodes(e)}
|
287
|
+
elsif element.is_a?(Hash)
|
288
|
+
element.keys.sort.each do |k|
|
289
|
+
label_blanknodes(element[k])
|
290
|
+
end
|
291
|
+
if node?(element) and !element.has_key?('@id')
|
292
|
+
element['@id'] = namer.get_name(nil)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
190
296
|
end
|
191
|
-
end
|
297
|
+
end
|
data/lib/json/ld/extensions.rb
CHANGED
@@ -62,6 +62,24 @@ module RDF
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
class Array
|
66
|
+
# Sort values, but impose special keyword ordering
|
67
|
+
# @yield a, b
|
68
|
+
# @yieldparam [Object] a
|
69
|
+
# @yieldparam [Object] b
|
70
|
+
# @yieldreturn [Integer]
|
71
|
+
# @return [Array]
|
72
|
+
KW_ORDER = %(@id @value @type @language @vocab @container @graph @list @set)
|
73
|
+
|
74
|
+
def kw_sort
|
75
|
+
self.sort do |a, b|
|
76
|
+
a = "@#{KW_ORDER.index(a)}" if KW_ORDER.include?(a)
|
77
|
+
b = "@#{KW_ORDER.index(b)}" if KW_ORDER.include?(b)
|
78
|
+
a <=> b
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
65
83
|
if RUBY_VERSION < "1.9"
|
66
84
|
class InsertOrderPreservingHash < Hash
|
67
85
|
include Enumerable
|
data/lib/json/ld/flatten.rb
CHANGED
@@ -13,14 +13,13 @@ module JSON::LD
|
|
13
13
|
# Graph name for results
|
14
14
|
# @param [Array] list
|
15
15
|
# List for saving list elements
|
16
|
-
# @param [
|
17
|
-
# @param [String] id
|
16
|
+
# @param [String] id (nil)
|
18
17
|
# Identifier already associated with element
|
19
|
-
def generate_node_map(element, node_map, graph, list
|
18
|
+
def generate_node_map(element, node_map, graph, list = nil, id = nil)
|
20
19
|
depth do
|
21
20
|
debug("nodeMap") {"element: #{element.inspect}, graph: #{graph}"}
|
22
21
|
if element.is_a?(Array)
|
23
|
-
element.map {|o| generate_node_map(o, node_map, graph, list
|
22
|
+
element.map {|o| generate_node_map(o, node_map, graph, list)}
|
24
23
|
elsif !element.is_a?(Hash) || value?(element)
|
25
24
|
list << element if list
|
26
25
|
else
|
@@ -48,7 +47,7 @@ module JSON::LD
|
|
48
47
|
when '@graph'
|
49
48
|
# If property is @graph, recursively call this algorithm passing value for element, nodeMap, nil for list and if graph is @merged use graph, otherwise use id for graph and then continue.
|
50
49
|
graph = graph == '@merged' ? '@merged' : id
|
51
|
-
generate_node_map(value, node_map, graph
|
50
|
+
generate_node_map(value, node_map, graph)
|
52
51
|
when /^@(?!type)/
|
53
52
|
# If property is not @type and is a keyword, merge property and value into node and then continue.
|
54
53
|
debug("nodeMap") {"merge keyword#{prop}: #{value.inspect}"}
|
@@ -75,7 +74,7 @@ module JSON::LD
|
|
75
74
|
}
|
76
75
|
|
77
76
|
# Recursively call this algorithm passing v for value, nodeMap, graph, and nil for list.
|
78
|
-
generate_node_map(v, node_map, graph, nil,
|
77
|
+
generate_node_map(v, node_map, graph, nil, name)
|
79
78
|
elsif list?(v)
|
80
79
|
# Otherwise if v has the property @list then recursively call this algorithm with the value of @list as element, nodeMap, graph, and a new array flattenedList as list.
|
81
80
|
debug("nodeMap") {"list value #{prop}: #{v.inspect}"}
|
@@ -83,8 +82,7 @@ module JSON::LD
|
|
83
82
|
generate_node_map(v['@list'],
|
84
83
|
node_map,
|
85
84
|
graph,
|
86
|
-
flattened_list
|
87
|
-
namer)
|
85
|
+
flattened_list)
|
88
86
|
# Create a new JSON object with the property @list set to flattenedList and add it to node for property.
|
89
87
|
(node[prop] ||= []) << {'@list' => flattened_list}
|
90
88
|
elsif prop == '@type'
|
data/lib/json/ld/frame.rb
CHANGED
@@ -36,7 +36,7 @@ module JSON::LD
|
|
36
36
|
debug("frame") {"embed: #{embed.inspect}, explicit: #{explicit.inspect}"}
|
37
37
|
|
38
38
|
# For each id and node from the set of matched nodes ordered by id
|
39
|
-
matches.keys.
|
39
|
+
matches.keys.kw_sort.each do |id|
|
40
40
|
element = matches[id]
|
41
41
|
# If the active property is null, set the map of embeds in state to an empty map
|
42
42
|
state = state.merge(:embeds => {}) if property.nil?
|
@@ -77,7 +77,7 @@ module JSON::LD
|
|
77
77
|
debug("frame") {"add embedded_node: #{embedded_node.inspect}"}
|
78
78
|
|
79
79
|
# Process each property and value in the matched node as follows
|
80
|
-
element.keys.
|
80
|
+
element.keys.kw_sort.each do |prop|
|
81
81
|
value = element[prop]
|
82
82
|
if prop[0,1] == '@'
|
83
83
|
# If property is a keyword, add property and a copy of value to output and continue with the next property from node
|
@@ -138,7 +138,7 @@ module JSON::LD
|
|
138
138
|
end
|
139
139
|
|
140
140
|
# Process each property and value in frame in lexographical order, where property is not a keyword, as follows:
|
141
|
-
frame.keys.
|
141
|
+
frame.keys.kw_sort.each do |prop|
|
142
142
|
next if prop[0,1] == '@' || output.has_key?(prop)
|
143
143
|
property_frame = frame[prop]
|
144
144
|
debug("frame") {"frame prop: #{prop.inspect}. property_frame: #{property_frame.inspect}"}
|
data/lib/json/ld/to_rdf.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'rdf'
|
1
2
|
require 'rdf/nquads'
|
2
3
|
|
3
4
|
module JSON::LD
|
@@ -21,7 +22,6 @@ module JSON::LD
|
|
21
22
|
# @yieldparam [RDF::Statement] statement
|
22
23
|
def statements(path, element, subject, property, name, &block)
|
23
24
|
debug(path) {"statements: e=#{element.inspect}, s=#{subject.inspect}, p=#{property.inspect}, n=#{name.inspect}"}
|
24
|
-
@node_seq = "t0" unless subject || property
|
25
25
|
|
26
26
|
traverse_result = depth do
|
27
27
|
case element
|
@@ -55,7 +55,7 @@ module JSON::LD
|
|
55
55
|
|
56
56
|
# 1.7) For each key in the JSON object that has not already been processed,
|
57
57
|
# perform the following steps:
|
58
|
-
element.keys.
|
58
|
+
element.keys.kw_sort.each do |key|
|
59
59
|
value = element[key]
|
60
60
|
active_property = case key
|
61
61
|
when '@type'
|
@@ -65,7 +65,7 @@ module JSON::LD
|
|
65
65
|
# Otherwise, if property is @graph, process value algorithm recursively, using active subject
|
66
66
|
# as graph name and null values for active subject and active property and then continue to
|
67
67
|
# next property
|
68
|
-
statements("#{path}[#{key}]", value, nil, nil, active_subject, &block)
|
68
|
+
statements("#{path}[#{key}]", value, nil, nil, (active_subject unless active_subject.node?), &block)
|
69
69
|
next
|
70
70
|
when /^@/
|
71
71
|
# Otherwise, if property is a keyword, skip this step.
|
@@ -154,9 +154,7 @@ module JSON::LD
|
|
154
154
|
##
|
155
155
|
# Create a new named node using the sequence
|
156
156
|
def node
|
157
|
-
|
158
|
-
@node_seq = @node_seq.succ
|
159
|
-
n
|
157
|
+
RDF::Node.new(namer.get_sym)
|
160
158
|
end
|
161
159
|
|
162
160
|
##
|