json-ld 3.1.3 → 3.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +138 -49
- data/VERSION +1 -1
- data/bin/jsonld +28 -31
- data/lib/json/ld.rb +8 -2
- data/lib/json/ld/api.rb +55 -38
- data/lib/json/ld/compact.rb +68 -40
- data/lib/json/ld/conneg.rb +1 -1
- data/lib/json/ld/context.rb +570 -521
- data/lib/json/ld/expand.rb +203 -84
- data/lib/json/ld/extensions.rb +4 -4
- data/lib/json/ld/flatten.rb +92 -9
- data/lib/json/ld/format.rb +21 -8
- data/lib/json/ld/frame.rb +8 -8
- data/lib/json/ld/from_rdf.rb +42 -19
- data/lib/json/ld/reader.rb +21 -11
- data/lib/json/ld/streaming_reader.rb +578 -0
- data/lib/json/ld/streaming_writer.rb +4 -4
- data/lib/json/ld/to_rdf.rb +11 -7
- data/lib/json/ld/utils.rb +13 -13
- data/lib/json/ld/writer.rb +12 -5
- data/spec/api_spec.rb +1 -1
- data/spec/compact_spec.rb +207 -3
- data/spec/context_spec.rb +4 -42
- data/spec/expand_spec.rb +631 -0
- data/spec/flatten_spec.rb +517 -1
- data/spec/from_rdf_spec.rb +181 -0
- data/spec/matchers.rb +1 -1
- data/spec/rdfstar_spec.rb +25 -0
- data/spec/reader_spec.rb +33 -34
- data/spec/spec_helper.rb +33 -0
- data/spec/streaming_reader_spec.rb +237 -0
- data/spec/suite_flatten_spec.rb +4 -0
- data/spec/suite_frame_spec.rb +7 -0
- data/spec/suite_helper.rb +25 -13
- data/spec/suite_to_rdf_spec.rb +1 -0
- data/spec/to_rdf_spec.rb +209 -3
- data/spec/writer_spec.rb +193 -0
- metadata +68 -63
data/lib/json/ld/extensions.rb
CHANGED
@@ -11,10 +11,10 @@ module RDF
|
|
11
11
|
class Statement
|
12
12
|
# Validate extended RDF
|
13
13
|
def valid_extended?
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
(
|
14
|
+
subject? && subject.resource? && subject.valid_extended? &&
|
15
|
+
predicate? && predicate.resource? && predicate.valid_extended? &&
|
16
|
+
object? && object.term? && object.valid_extended? &&
|
17
|
+
(graph? ? (graph_name.resource? && graph_name.valid_extended?) : true)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
data/lib/json/ld/flatten.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
# frozen_string_literal: true
|
3
|
+
require 'json/canonicalization'
|
4
|
+
|
3
5
|
module JSON::LD
|
4
6
|
module Flatten
|
5
7
|
include Utils
|
@@ -7,6 +9,10 @@ module JSON::LD
|
|
7
9
|
##
|
8
10
|
# This algorithm creates a JSON object node map holding an indexed representation of the graphs and nodes represented in the passed expanded document. All nodes that are not uniquely identified by an IRI get assigned a (new) blank node identifier. The resulting node map will have a member for every graph in the document whose value is another object with a member for every node represented in the document. The default graph is stored under the @default member, all other graphs are stored under their graph name.
|
9
11
|
#
|
12
|
+
# For RDF*/JSON-LD*:
|
13
|
+
# * Values of `@id` can be an object (embedded node); when these are used as keys in a Node Map, they are serialized as canonical JSON, and de-serialized when flattening.
|
14
|
+
# * The presence of `@annotation` implies an embedded node and the annotation object is removed from the node/value object in which it appears.
|
15
|
+
#
|
10
16
|
# @param [Array, Hash] element
|
11
17
|
# Expanded JSON-LD input
|
12
18
|
# @param [Hash] graph_map A map of graph name to subjects
|
@@ -16,12 +22,15 @@ module JSON::LD
|
|
16
22
|
# Node identifier
|
17
23
|
# @param [String] active_property (nil)
|
18
24
|
# Property within current node
|
25
|
+
# @param [Boolean] reverse (false)
|
26
|
+
# Processing a reverse relationship
|
19
27
|
# @param [Array] list (nil)
|
20
28
|
# Used when property value is a list
|
21
29
|
def create_node_map(element, graph_map,
|
22
30
|
active_graph: '@default',
|
23
31
|
active_subject: nil,
|
24
32
|
active_property: nil,
|
33
|
+
reverse: false,
|
25
34
|
list: nil)
|
26
35
|
if element.is_a?(Array)
|
27
36
|
# If element is an array, process each entry in element recursively by passing item for element, node map, active graph, active subject, active property, and list.
|
@@ -30,21 +39,45 @@ module JSON::LD
|
|
30
39
|
active_graph: active_graph,
|
31
40
|
active_subject: active_subject,
|
32
41
|
active_property: active_property,
|
42
|
+
reverse: false,
|
33
43
|
list: list)
|
34
44
|
end
|
35
45
|
elsif !element.is_a?(Hash)
|
36
46
|
raise "Expected hash or array to create_node_map, got #{element.inspect}"
|
37
47
|
else
|
38
48
|
graph = (graph_map[active_graph] ||= {})
|
39
|
-
subject_node = graph[active_subject]
|
49
|
+
subject_node = !reverse && graph[active_subject.is_a?(Hash) ? active_subject.to_json_c14n : active_subject]
|
40
50
|
|
41
51
|
# Transform BNode types
|
42
|
-
if element.
|
52
|
+
if element.key?('@type')
|
43
53
|
element['@type'] = Array(element['@type']).map {|t| blank_node?(t) ? namer.get_name(t) : t}
|
44
54
|
end
|
45
55
|
|
46
56
|
if value?(element)
|
47
57
|
element['@type'] = element['@type'].first if element ['@type']
|
58
|
+
|
59
|
+
# For rdfstar, if value contains an `@annotation` member ...
|
60
|
+
# note: active_subject will not be nil, and may be an object itself.
|
61
|
+
if element.key?('@annotation')
|
62
|
+
# rdfstar being true is implicit, as it is checked in expansion
|
63
|
+
as = node_reference?(active_subject) ?
|
64
|
+
active_subject['@id'] :
|
65
|
+
active_subject
|
66
|
+
star_subject = {
|
67
|
+
"@id" => as,
|
68
|
+
active_property => [element]
|
69
|
+
}
|
70
|
+
|
71
|
+
# Note that annotation is an array, make the reified subject the id of each member of that array.
|
72
|
+
annotation = element.delete('@annotation').map do |a|
|
73
|
+
a.merge('@id' => star_subject)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Invoke recursively using annotation.
|
77
|
+
create_node_map(annotation, graph_map,
|
78
|
+
active_graph: active_graph)
|
79
|
+
end
|
80
|
+
|
48
81
|
if list.nil?
|
49
82
|
add_value(subject_node, active_property, element, property_is_array: true, allow_duplicate: false)
|
50
83
|
else
|
@@ -64,13 +97,19 @@ module JSON::LD
|
|
64
97
|
end
|
65
98
|
else
|
66
99
|
# Element is a node object
|
67
|
-
id = element.delete('@id')
|
68
|
-
id
|
100
|
+
ser_id = id = element.delete('@id')
|
101
|
+
if id.is_a?(Hash)
|
102
|
+
# Index graph using serialized id
|
103
|
+
ser_id = id.to_json_c14n
|
104
|
+
elsif id.nil?
|
105
|
+
ser_id = id = namer.get_name
|
106
|
+
end
|
69
107
|
|
70
|
-
node = graph[
|
108
|
+
node = graph[ser_id] ||= {'@id' => id}
|
71
109
|
|
72
|
-
if
|
73
|
-
#
|
110
|
+
if reverse
|
111
|
+
# Note: active_subject is a Hash
|
112
|
+
# We're processing a reverse-property relationship.
|
74
113
|
add_value(node, active_property, active_subject, property_is_array: true, allow_duplicate: false)
|
75
114
|
elsif active_property
|
76
115
|
reference = {'@id' => id}
|
@@ -81,7 +120,30 @@ module JSON::LD
|
|
81
120
|
end
|
82
121
|
end
|
83
122
|
|
84
|
-
if
|
123
|
+
# For rdfstar, if node contains an `@annotation` member ...
|
124
|
+
# note: active_subject will not be nil, and may be an object itself.
|
125
|
+
# XXX: what if we're reversing an annotation?
|
126
|
+
if element.key?('@annotation')
|
127
|
+
# rdfstar being true is implicit, as it is checked in expansion
|
128
|
+
as = node_reference?(active_subject) ?
|
129
|
+
active_subject['@id'] :
|
130
|
+
active_subject
|
131
|
+
star_subject = reverse ?
|
132
|
+
{"@id" => node['@id'], active_property => [{'@id' => as}]} :
|
133
|
+
{"@id" => as, active_property => [{'@id' => node['@id']}]}
|
134
|
+
|
135
|
+
# Note that annotation is an array, make the reified subject the id of each member of that array.
|
136
|
+
annotation = element.delete('@annotation').map do |a|
|
137
|
+
a.merge('@id' => star_subject)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Invoke recursively using annotation.
|
141
|
+
create_node_map(annotation, graph_map,
|
142
|
+
active_graph: active_graph,
|
143
|
+
active_subject: star_subject)
|
144
|
+
end
|
145
|
+
|
146
|
+
if element.key?('@type')
|
85
147
|
add_value(node, '@type', element.delete('@type'), property_is_array: true, allow_duplicate: false)
|
86
148
|
end
|
87
149
|
|
@@ -99,7 +161,8 @@ module JSON::LD
|
|
99
161
|
create_node_map(value, graph_map,
|
100
162
|
active_graph: active_graph,
|
101
163
|
active_subject: referenced_node,
|
102
|
-
active_property: property
|
164
|
+
active_property: property,
|
165
|
+
reverse: true)
|
103
166
|
end
|
104
167
|
end
|
105
168
|
end
|
@@ -128,7 +191,27 @@ module JSON::LD
|
|
128
191
|
end
|
129
192
|
end
|
130
193
|
|
194
|
+
##
|
195
|
+
# Rename blank nodes recursively within an embedded object
|
196
|
+
#
|
197
|
+
# @param [Object] node
|
198
|
+
# @return [Hash]
|
199
|
+
def rename_bnodes(node)
|
200
|
+
case node
|
201
|
+
when Array
|
202
|
+
node.map {|n| rename_bnodes(n)}
|
203
|
+
when Hash
|
204
|
+
node.inject({}) do |memo, (k, v)|
|
205
|
+
v = namer.get_name(v) if k == '@id' && v.is_a?(String) && blank_node?(v)
|
206
|
+
memo.merge(k => rename_bnodes(v))
|
207
|
+
end
|
208
|
+
else
|
209
|
+
node
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
131
213
|
private
|
214
|
+
|
132
215
|
##
|
133
216
|
# Merge nodes from all graphs in the graph_map into a new node map
|
134
217
|
#
|
data/lib/json/ld/format.rb
CHANGED
@@ -57,10 +57,11 @@ module JSON::LD
|
|
57
57
|
lambda: ->(files, **options) do
|
58
58
|
out = options[:output] || $stdout
|
59
59
|
out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java"
|
60
|
-
options = options.merge(expandContext: options.delete(:context)) if options.
|
60
|
+
options = options.merge(expandContext: options.delete(:context)) if options.key?(:context)
|
61
|
+
options[:base] ||= options[:base_uri]
|
61
62
|
if options[:format] == :jsonld
|
62
63
|
if files.empty?
|
63
|
-
# If files are empty, either use options[:
|
64
|
+
# If files are empty, either use options[:evaluate] or STDIN
|
64
65
|
input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN
|
65
66
|
input.set_encoding(options.fetch(:encoding, Encoding::UTF_8))
|
66
67
|
JSON::LD::API.expand(input, validate: false, **options) do |expanded|
|
@@ -93,9 +94,10 @@ module JSON::LD
|
|
93
94
|
raise ArgumentError, "Compacting requires a context" unless options[:context]
|
94
95
|
out = options[:output] || $stdout
|
95
96
|
out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java"
|
97
|
+
options[:base] ||= options[:base_uri]
|
96
98
|
if options[:format] == :jsonld
|
97
99
|
if files.empty?
|
98
|
-
# If files are empty, either use options[:
|
100
|
+
# If files are empty, either use options[:evaluate] or STDIN
|
99
101
|
input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN
|
100
102
|
input.set_encoding(options.fetch(:encoding, Encoding::UTF_8))
|
101
103
|
JSON::LD::API.compact(input, options[:context], **options) do |compacted|
|
@@ -126,7 +128,7 @@ module JSON::LD
|
|
126
128
|
control: :url2,
|
127
129
|
use: :required,
|
128
130
|
on: ["--context CONTEXT"],
|
129
|
-
description: "Context to use when compacting.") {|arg| RDF::URI(arg)},
|
131
|
+
description: "Context to use when compacting.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))},
|
130
132
|
]
|
131
133
|
},
|
132
134
|
flatten: {
|
@@ -137,9 +139,10 @@ module JSON::LD
|
|
137
139
|
lambda: ->(files, **options) do
|
138
140
|
out = options[:output] || $stdout
|
139
141
|
out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java"
|
142
|
+
options[:base] ||= options[:base_uri]
|
140
143
|
if options[:format] == :jsonld
|
141
144
|
if files.empty?
|
142
|
-
# If files are empty, either use options[:
|
145
|
+
# If files are empty, either use options[:evaluate] or STDIN
|
143
146
|
input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN
|
144
147
|
input.set_encoding(options.fetch(:encoding, Encoding::UTF_8))
|
145
148
|
JSON::LD::API.flatten(input, options[:context], **options) do |flattened|
|
@@ -162,7 +165,16 @@ module JSON::LD
|
|
162
165
|
end
|
163
166
|
end
|
164
167
|
end
|
165
|
-
end
|
168
|
+
end,
|
169
|
+
options: [
|
170
|
+
RDF::CLI::Option.new(
|
171
|
+
symbol: :context,
|
172
|
+
datatype: RDF::URI,
|
173
|
+
control: :url2,
|
174
|
+
use: :required,
|
175
|
+
on: ["--context CONTEXT"],
|
176
|
+
description: "Context to use when compacting.") {|arg| RDF::URI(arg)},
|
177
|
+
]
|
166
178
|
},
|
167
179
|
frame: {
|
168
180
|
description: "Frame JSON-LD or parsed RDF",
|
@@ -173,9 +185,10 @@ module JSON::LD
|
|
173
185
|
raise ArgumentError, "Framing requires a frame" unless options[:frame]
|
174
186
|
out = options[:output] || $stdout
|
175
187
|
out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java"
|
188
|
+
options[:base] ||= options[:base_uri]
|
176
189
|
if options[:format] == :jsonld
|
177
190
|
if files.empty?
|
178
|
-
# If files are empty, either use options[:
|
191
|
+
# If files are empty, either use options[:evaluate] or STDIN
|
179
192
|
input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN
|
180
193
|
input.set_encoding(options.fetch(:encoding, Encoding::UTF_8))
|
181
194
|
JSON::LD::API.frame(input, options[:frame], **options) do |framed|
|
@@ -207,7 +220,7 @@ module JSON::LD
|
|
207
220
|
control: :url2,
|
208
221
|
use: :required,
|
209
222
|
on: ["--frame FRAME"],
|
210
|
-
description: "Frame to use when serializing.") {|arg| RDF::URI(arg)}
|
223
|
+
description: "Frame to use when serializing.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))}
|
211
224
|
]
|
212
225
|
},
|
213
226
|
}
|
data/lib/json/ld/frame.rb
CHANGED
@@ -52,7 +52,7 @@ module JSON::LD
|
|
52
52
|
state[:uniqueEmbeds][state[:graph]] ||= {}
|
53
53
|
end
|
54
54
|
|
55
|
-
if flags[:embed] == '@link' && link.
|
55
|
+
if flags[:embed] == '@link' && link.key?(id)
|
56
56
|
# add existing linked subject
|
57
57
|
add_frame_output(parent, property, link[id])
|
58
58
|
next
|
@@ -66,7 +66,7 @@ module JSON::LD
|
|
66
66
|
warn "[DEPRECATION] #{flags[:embed]} is not a valid value of @embed in 1.1 mode.\n"
|
67
67
|
end
|
68
68
|
|
69
|
-
if !state[:embedded] && state[:uniqueEmbeds][state[:graph]].
|
69
|
+
if !state[:embedded] && state[:uniqueEmbeds][state[:graph]].key?(id)
|
70
70
|
# Skip adding this node object to the top-level, as it was included in another node object
|
71
71
|
next
|
72
72
|
elsif state[:embedded] &&
|
@@ -76,7 +76,7 @@ module JSON::LD
|
|
76
76
|
next
|
77
77
|
elsif state[:embedded] &&
|
78
78
|
%w(@first @once).include?(flags[:embed]) &&
|
79
|
-
state[:uniqueEmbeds][state[:graph]].
|
79
|
+
state[:uniqueEmbeds][state[:graph]].key?(id)
|
80
80
|
|
81
81
|
# if only the first match should be embedded
|
82
82
|
# Embed unless already embedded
|
@@ -97,7 +97,7 @@ module JSON::LD
|
|
97
97
|
state[:subjectStack] << {subject: subject, graph: state[:graph]}
|
98
98
|
|
99
99
|
# Subject is also the name of a graph
|
100
|
-
if state[:graphMap].
|
100
|
+
if state[:graphMap].key?(id)
|
101
101
|
# check frame's "@graph" to see what to do next
|
102
102
|
# 1. if it doesn't exist and state.graph === "@merged", don't recurse
|
103
103
|
# 2. if it doesn't exist and state.graph !== "@merged", recurse
|
@@ -105,7 +105,7 @@ module JSON::LD
|
|
105
105
|
# 4. if "@default" then don't recurse
|
106
106
|
# 5. recurse
|
107
107
|
recurse, subframe = false, nil
|
108
|
-
if !frame.
|
108
|
+
if !frame.key?('@graph')
|
109
109
|
recurse, subframe = (state[:graph] != '@merged'), {}
|
110
110
|
else
|
111
111
|
subframe = frame['@graph'].first
|
@@ -134,7 +134,7 @@ module JSON::LD
|
|
134
134
|
end
|
135
135
|
|
136
136
|
# explicit is on and property isn't in frame, skip processing
|
137
|
-
next if flags[:explicit] && !frame.
|
137
|
+
next if flags[:explicit] && !frame.key?(prop)
|
138
138
|
|
139
139
|
# add objects
|
140
140
|
objects.each do |o|
|
@@ -267,7 +267,7 @@ module JSON::LD
|
|
267
267
|
# If, after replacement, an array contains only the value null remove the value, leaving an empty array.
|
268
268
|
input.map {|o| cleanup_preserve(o)}
|
269
269
|
when Hash
|
270
|
-
if input.
|
270
|
+
if input.key?('@preserve')
|
271
271
|
# Replace with the content of `@preserve`
|
272
272
|
cleanup_preserve(input['@preserve'].first)
|
273
273
|
else
|
@@ -388,7 +388,7 @@ module JSON::LD
|
|
388
388
|
is_empty = v.empty?
|
389
389
|
if v = v.first
|
390
390
|
validate_frame(v)
|
391
|
-
has_default = v.
|
391
|
+
has_default = v.key?('@default')
|
392
392
|
end
|
393
393
|
|
394
394
|
# No longer a wildcard pattern if frame has any non-keyword properties
|
data/lib/json/ld/from_rdf.rb
CHANGED
@@ -14,16 +14,14 @@ 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
|
-
#
|
18
|
-
# Ensure output objects have keys ordered properly
|
17
|
+
#
|
19
18
|
# @return [Array<Hash>] the JSON-LD document in normalized form
|
20
|
-
def from_statements(dataset, useRdfType: false, useNativeTypes: false
|
19
|
+
def from_statements(dataset, useRdfType: false, useNativeTypes: false)
|
21
20
|
default_graph = {}
|
22
21
|
graph_map = {'@default' => default_graph}
|
23
22
|
referenced_once = {}
|
24
23
|
|
25
24
|
value = nil
|
26
|
-
ec = @context
|
27
25
|
|
28
26
|
# Create an entry for compound-literal node detection
|
29
27
|
compound_literal_subjects = {}
|
@@ -34,7 +32,7 @@ module JSON::LD
|
|
34
32
|
dataset.each do |statement|
|
35
33
|
#log_debug("statement") { statement.to_nquads.chomp}
|
36
34
|
|
37
|
-
name = statement.graph_name ?
|
35
|
+
name = statement.graph_name ? @context.expand_iri(statement.graph_name, base: @options[:base]).to_s : '@default'
|
38
36
|
|
39
37
|
# Create a graph entry as needed
|
40
38
|
node_map = graph_map[name] ||= {}
|
@@ -42,30 +40,29 @@ module JSON::LD
|
|
42
40
|
|
43
41
|
default_graph[name] ||= {'@id' => name} unless name == '@default'
|
44
42
|
|
45
|
-
subject =
|
46
|
-
node = node_map[subject] ||=
|
43
|
+
subject = statement.subject.to_s
|
44
|
+
node = node_map[subject] ||= resource_representation(statement.subject,useNativeTypes)
|
47
45
|
|
48
46
|
# If predicate is rdf:datatype, note subject in compound literal subjects map
|
49
47
|
if @options[:rdfDirection] == 'compound-literal' && statement.predicate == RDF.to_uri + 'direction'
|
50
48
|
compound_literal_subjects[name][subject] ||= true
|
51
49
|
end
|
52
50
|
|
53
|
-
# If object is an IRI
|
54
|
-
|
55
|
-
statement.object.
|
51
|
+
# 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.
|
52
|
+
unless statement.object.literal?
|
53
|
+
node_map[statement.object.to_s] ||=
|
54
|
+
resource_representation(statement.object, useNativeTypes)
|
55
|
+
end
|
56
56
|
|
57
57
|
# 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.
|
58
|
+
# XXX JSON-LD* does not support embedded value of @type
|
58
59
|
if statement.predicate == RDF.type && statement.object.resource? && !useRdfType
|
59
60
|
merge_value(node, '@type', statement.object.to_s)
|
60
61
|
next
|
61
62
|
end
|
62
63
|
|
63
64
|
# Set value to the result of using the RDF to Object Conversion algorithm, passing object, rdfDirection, and use native types.
|
64
|
-
value =
|
65
|
-
statement.object,
|
66
|
-
rdfDirection: @options[:rdfDirection],
|
67
|
-
useNativeTypes: useNativeTypes,
|
68
|
-
log_depth: @options[:log_depth])
|
65
|
+
value = resource_representation(statement.object, useNativeTypes)
|
69
66
|
|
70
67
|
merge_value(node, statement.predicate.to_s, value)
|
71
68
|
|
@@ -78,7 +75,7 @@ module JSON::LD
|
|
78
75
|
property: statement.predicate.to_s,
|
79
76
|
value: value
|
80
77
|
})
|
81
|
-
elsif referenced_once.
|
78
|
+
elsif referenced_once.key?(statement.object.to_s)
|
82
79
|
referenced_once[statement.object.to_s] = false
|
83
80
|
elsif statement.object.node?
|
84
81
|
referenced_once[statement.object.to_s] = {
|
@@ -147,11 +144,11 @@ module JSON::LD
|
|
147
144
|
end
|
148
145
|
|
149
146
|
result = []
|
150
|
-
default_graph.keys.opt_sort(ordered: ordered).each do |subject|
|
147
|
+
default_graph.keys.opt_sort(ordered: @options[:ordered]).each do |subject|
|
151
148
|
node = default_graph[subject]
|
152
|
-
if graph_map.
|
149
|
+
if graph_map.key?(subject)
|
153
150
|
node['@graph'] = []
|
154
|
-
graph_map[subject].keys.opt_sort(ordered: ordered).each do |s|
|
151
|
+
graph_map[subject].keys.opt_sort(ordered: @options[:ordered]).each do |s|
|
155
152
|
n = graph_map[subject][s]
|
156
153
|
n.delete(:usages)
|
157
154
|
node['@graph'] << n unless node_reference?(n)
|
@@ -163,5 +160,31 @@ module JSON::LD
|
|
163
160
|
#log_debug("fromRdf") {result.to_json(JSON_STATE) rescue 'malformed json'}
|
164
161
|
result
|
165
162
|
end
|
163
|
+
|
164
|
+
private
|
165
|
+
def resource_representation(resource, useNativeTypes)
|
166
|
+
case resource
|
167
|
+
when RDF::Statement
|
168
|
+
# Note, if either subject or object are a BNode which is used elsewhere,
|
169
|
+
# this might not work will with the BNode accounting from above.
|
170
|
+
rep = {'@id' => resource_representation(resource.subject, false)}
|
171
|
+
if resource.predicate == RDF.type
|
172
|
+
rep['@id'].merge!('@type' => resource.object.to_s)
|
173
|
+
else
|
174
|
+
rep['@id'].merge!(
|
175
|
+
resource.predicate.to_s =>
|
176
|
+
as_array(resource_representation(resource.object, useNativeTypes)))
|
177
|
+
end
|
178
|
+
rep
|
179
|
+
when RDF::Literal
|
180
|
+
@context.expand_value(nil,
|
181
|
+
resource,
|
182
|
+
rdfDirection: @options[:rdfDirection],
|
183
|
+
useNativeTypes: useNativeTypes,
|
184
|
+
base: @options[:base])
|
185
|
+
else
|
186
|
+
{'@id' => resource.to_s}
|
187
|
+
end
|
188
|
+
end
|
166
189
|
end
|
167
190
|
end
|