json-ld 3.2.3 → 3.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/json/ld/api.rb +807 -764
  4. data/lib/json/ld/compact.rb +304 -304
  5. data/lib/json/ld/conneg.rb +179 -161
  6. data/lib/json/ld/context.rb +2080 -1945
  7. data/lib/json/ld/expand.rb +745 -666
  8. data/lib/json/ld/extensions.rb +14 -13
  9. data/lib/json/ld/flatten.rb +257 -247
  10. data/lib/json/ld/format.rb +202 -194
  11. data/lib/json/ld/frame.rb +525 -502
  12. data/lib/json/ld/from_rdf.rb +224 -166
  13. data/lib/json/ld/html/nokogiri.rb +123 -121
  14. data/lib/json/ld/html/rexml.rb +151 -147
  15. data/lib/json/ld/reader.rb +107 -100
  16. data/lib/json/ld/resource.rb +224 -205
  17. data/lib/json/ld/streaming_reader.rb +574 -507
  18. data/lib/json/ld/streaming_writer.rb +93 -92
  19. data/lib/json/ld/to_rdf.rb +171 -167
  20. data/lib/json/ld/utils.rb +270 -264
  21. data/lib/json/ld/version.rb +24 -14
  22. data/lib/json/ld/writer.rb +334 -311
  23. data/lib/json/ld.rb +103 -96
  24. metadata +78 -209
  25. data/spec/api_spec.rb +0 -132
  26. data/spec/compact_spec.rb +0 -3482
  27. data/spec/conneg_spec.rb +0 -373
  28. data/spec/context_spec.rb +0 -2036
  29. data/spec/expand_spec.rb +0 -4496
  30. data/spec/flatten_spec.rb +0 -1203
  31. data/spec/format_spec.rb +0 -115
  32. data/spec/frame_spec.rb +0 -2498
  33. data/spec/from_rdf_spec.rb +0 -1005
  34. data/spec/matchers.rb +0 -20
  35. data/spec/rdfstar_spec.rb +0 -25
  36. data/spec/reader_spec.rb +0 -883
  37. data/spec/resource_spec.rb +0 -76
  38. data/spec/spec_helper.rb +0 -281
  39. data/spec/streaming_reader_spec.rb +0 -237
  40. data/spec/streaming_writer_spec.rb +0 -145
  41. data/spec/suite_compact_spec.rb +0 -22
  42. data/spec/suite_expand_spec.rb +0 -36
  43. data/spec/suite_flatten_spec.rb +0 -34
  44. data/spec/suite_frame_spec.rb +0 -29
  45. data/spec/suite_from_rdf_spec.rb +0 -22
  46. data/spec/suite_helper.rb +0 -411
  47. data/spec/suite_html_spec.rb +0 -22
  48. data/spec/suite_http_spec.rb +0 -35
  49. data/spec/suite_remote_doc_spec.rb +0 -22
  50. data/spec/suite_to_rdf_spec.rb +0 -30
  51. data/spec/support/extensions.rb +0 -44
  52. data/spec/test-files/test-1-compacted.jsonld +0 -10
  53. data/spec/test-files/test-1-context.jsonld +0 -7
  54. data/spec/test-files/test-1-expanded.jsonld +0 -5
  55. data/spec/test-files/test-1-input.jsonld +0 -10
  56. data/spec/test-files/test-1-rdf.ttl +0 -8
  57. data/spec/test-files/test-2-compacted.jsonld +0 -20
  58. data/spec/test-files/test-2-context.jsonld +0 -7
  59. data/spec/test-files/test-2-expanded.jsonld +0 -16
  60. data/spec/test-files/test-2-input.jsonld +0 -20
  61. data/spec/test-files/test-2-rdf.ttl +0 -14
  62. data/spec/test-files/test-3-compacted.jsonld +0 -11
  63. data/spec/test-files/test-3-context.jsonld +0 -8
  64. data/spec/test-files/test-3-expanded.jsonld +0 -10
  65. data/spec/test-files/test-3-input.jsonld +0 -11
  66. data/spec/test-files/test-3-rdf.ttl +0 -8
  67. data/spec/test-files/test-4-compacted.jsonld +0 -10
  68. data/spec/test-files/test-4-context.jsonld +0 -7
  69. data/spec/test-files/test-4-expanded.jsonld +0 -6
  70. data/spec/test-files/test-4-input.jsonld +0 -10
  71. data/spec/test-files/test-4-rdf.ttl +0 -5
  72. data/spec/test-files/test-5-compacted.jsonld +0 -13
  73. data/spec/test-files/test-5-context.jsonld +0 -7
  74. data/spec/test-files/test-5-expanded.jsonld +0 -9
  75. data/spec/test-files/test-5-input.jsonld +0 -13
  76. data/spec/test-files/test-5-rdf.ttl +0 -7
  77. data/spec/test-files/test-6-compacted.jsonld +0 -10
  78. data/spec/test-files/test-6-context.jsonld +0 -7
  79. data/spec/test-files/test-6-expanded.jsonld +0 -10
  80. data/spec/test-files/test-6-input.jsonld +0 -10
  81. data/spec/test-files/test-6-rdf.ttl +0 -6
  82. data/spec/test-files/test-7-compacted.jsonld +0 -23
  83. data/spec/test-files/test-7-context.jsonld +0 -4
  84. data/spec/test-files/test-7-expanded.jsonld +0 -20
  85. data/spec/test-files/test-7-input.jsonld +0 -23
  86. data/spec/test-files/test-7-rdf.ttl +0 -14
  87. data/spec/test-files/test-8-compacted.jsonld +0 -34
  88. data/spec/test-files/test-8-context.jsonld +0 -11
  89. data/spec/test-files/test-8-expanded.jsonld +0 -24
  90. data/spec/test-files/test-8-frame.jsonld +0 -18
  91. data/spec/test-files/test-8-framed.jsonld +0 -25
  92. data/spec/test-files/test-8-input.jsonld +0 -30
  93. data/spec/test-files/test-8-rdf.ttl +0 -15
  94. data/spec/test-files/test-9-compacted.jsonld +0 -20
  95. data/spec/test-files/test-9-context.jsonld +0 -13
  96. data/spec/test-files/test-9-expanded.jsonld +0 -14
  97. data/spec/test-files/test-9-input.jsonld +0 -12
  98. data/spec/to_rdf_spec.rb +0 -1551
  99. data/spec/writer_spec.rb +0 -427
@@ -1,195 +1,253 @@
1
- # -*- encoding: utf-8 -*-
2
1
  # frozen_string_literal: true
3
- require 'rdf/nquads'
4
-
5
- module JSON::LD
6
- module FromRDF
7
- include Utils
8
-
9
- ##
10
- # Generate a JSON-LD array representation from an array of `RDF::Statement`.
11
- # Representation is in expanded form
12
- #
13
- # @param [Array<RDF::Statement>, RDF::Enumerable] dataset
14
- # @param [Boolean] useRdfType (false)
15
- # If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
16
- # @param [Boolean] useNativeTypes (false) use native representations
17
- #
18
- # @return [Array<Hash>] the JSON-LD document in normalized form
19
- def from_statements(dataset, useRdfType: false, useNativeTypes: false)
20
- default_graph = {}
21
- graph_map = {'@default' => default_graph}
22
- referenced_once = {}
23
-
24
- value = nil
25
2
 
26
- # Create an entry for compound-literal node detection
27
- compound_literal_subjects = {}
28
-
29
- # Create a map for node to object representation
30
-
31
- # For each statement in dataset
32
- dataset.each do |statement|
33
- #log_debug("statement") { statement.to_nquads.chomp}
3
+ require 'rdf/nquads'
34
4
 
35
- name = statement.graph_name ? @context.expand_iri(statement.graph_name, base: @options[:base]).to_s : '@default'
5
+ module JSON
6
+ module LD
7
+ module FromRDF
8
+ include Utils
9
+
10
+ ##
11
+ # Generate a JSON-LD array representation from an array of `RDF::Statement`.
12
+ # Representation is in expanded form
13
+ #
14
+ # @param [Array<RDF::Statement>, RDF::Enumerable] dataset
15
+ # @param [Boolean] useRdfType (false)
16
+ # If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
17
+ # @param [Boolean] useNativeTypes (false) use native representations
18
+ # @param extendedRepresentation (false)
19
+ # Use the extended internal representation for native types.
20
+ #
21
+ # @return [Array<Hash>] the JSON-LD document in normalized form
22
+ def from_statements(dataset, useRdfType: false, useNativeTypes: false, extendedRepresentation: false)
23
+ default_graph = {}
24
+ graph_map = { '@default' => default_graph }
25
+ referenced_once = {}
26
+
27
+ value = nil
28
+
29
+ # Create an entry for compound-literal node detection
30
+ compound_literal_subjects = {}
31
+
32
+ # Create a map for node to object representation
33
+
34
+ # For each statement in dataset
35
+ dataset.each do |statement|
36
+ # log_debug("statement") { statement.to_nquads.chomp}
37
+
38
+ name = if statement.graph_name
39
+ @context.expand_iri(statement.graph_name,
40
+ base: @options[:base]).to_s
41
+ else
42
+ '@default'
43
+ end
36
44
 
37
- # Create a graph entry as needed
38
- node_map = graph_map[name] ||= {}
39
- compound_literal_subjects[name] ||= {}
45
+ # Create a graph entry as needed
46
+ node_map = graph_map[name] ||= {}
47
+ compound_literal_subjects[name] ||= {}
40
48
 
41
- default_graph[name] ||= {'@id' => name} unless name == '@default'
49
+ default_graph[name] ||= { '@id' => name } unless name == '@default'
42
50
 
43
- subject = statement.subject.statement? ?
44
- resource_representation(statement.subject, useNativeTypes)['@id'].to_json_c14n :
45
- statement.subject.to_s
46
- node = node_map[subject] ||= resource_representation(statement.subject, useNativeTypes)
51
+ subject = if statement.subject.statement?
52
+ resource_representation(statement.subject, useNativeTypes, extendedRepresentation)['@id'].to_json_c14n
53
+ else
54
+ statement.subject.to_s
55
+ end
56
+ node = node_map[subject] ||= resource_representation(statement.subject, useNativeTypes,
57
+ extendedRepresentation)
47
58
 
48
- # If predicate is rdf:datatype, note subject in compound literal subjects map
49
- if @options[:rdfDirection] == 'compound-literal' && statement.predicate == RDF.to_uri + 'direction'
50
- compound_literal_subjects[name][subject] ||= true
51
- end
59
+ # If predicate is rdf:datatype, note subject in compound literal subjects map
60
+ if @options[:rdfDirection] == 'compound-literal' && statement.predicate == RDF_DIRECTION
61
+ compound_literal_subjects[name][subject] ||= true
62
+ end
52
63
 
53
- # 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
- unless statement.object.literal?
55
- object = statement.object.statement? ?
56
- resource_representation(statement.object, useNativeTypes)['@id'].to_json_c14n :
57
- statement.object.to_s
58
- node_map[object] ||=
59
- resource_representation(statement.object, useNativeTypes)
60
- end
64
+ # 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.
65
+ unless statement.object.literal?
66
+ object = if statement.object.statement?
67
+ resource_representation(statement.object, useNativeTypes, extendedRepresentation)['@id'].to_json_c14n
68
+ else
69
+ statement.object.to_s
70
+ end
71
+ node_map[object] ||=
72
+ resource_representation(statement.object, useNativeTypes, extendedRepresentation)
73
+ end
61
74
 
62
- # 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.
63
- if statement.predicate == RDF.type && statement.object.resource? && !useRdfType
64
- merge_value(node, '@type', statement.object.to_s)
65
- next
66
- end
75
+ # 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.
76
+ if statement.predicate == RDF.type && statement.object.resource? && !useRdfType
77
+ merge_value(node, '@type', statement.object.to_s)
78
+ next
79
+ end
67
80
 
68
- # 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)
70
-
71
- merge_value(node, statement.predicate.to_s, value)
72
-
73
- # If object is a blank node identifier or rdf:nil, it might represent the a list node:
74
- if statement.object == RDF.nil
75
- # 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.
76
- object = node_map[statement.object.to_s]
77
- merge_value(object, :usages, {
78
- node: node,
79
- property: statement.predicate.to_s,
80
- value: value
81
- })
82
- elsif referenced_once.key?(statement.object.to_s)
83
- referenced_once[statement.object.to_s] = false
84
- elsif statement.object.node?
85
- referenced_once[statement.object.to_s] = {
86
- node: node,
87
- property: statement.predicate.to_s,
88
- value: value
89
- }
81
+ # Set value to the result of using the RDF to Object Conversion algorithm, passing object, rdfDirection, and use native types.
82
+ value = resource_representation(statement.object, useNativeTypes, extendedRepresentation)
83
+
84
+ merge_value(node, statement.predicate.to_s, value)
85
+
86
+ # If object is a blank node identifier or rdf:nil, it might represent the a list node:
87
+ if statement.object == RDF.nil
88
+ # 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.
89
+ object = node_map[statement.object.to_s]
90
+ merge_value(object, :usages, {
91
+ node: node,
92
+ property: statement.predicate.to_s,
93
+ value: value
94
+ })
95
+ elsif referenced_once.key?(statement.object.to_s)
96
+ referenced_once[statement.object.to_s] = false
97
+ elsif statement.object.node?
98
+ referenced_once[statement.object.to_s] = {
99
+ node: node,
100
+ property: statement.predicate.to_s,
101
+ value: value
102
+ }
103
+ end
90
104
  end
91
- end
92
105
 
93
- # For each name and graph object in graph map:
94
- graph_map.each do |name, graph_object|
95
-
96
- # If rdfDirection is compound-literal, check referenced_once for entries from compound_literal_subjects
97
- compound_literal_subjects.fetch(name, {}).keys.each do |cl|
98
- node = referenced_once[cl][:node]
99
- next unless node.is_a?(Hash)
100
- property = referenced_once[cl][:property]
101
- value = referenced_once[cl][:value]
102
- cl_node = graph_map[name].delete(cl)
103
- next unless cl_node.is_a?(Hash)
104
- node[property].select do |v|
105
- next unless v['@id'] == cl
106
- v.delete('@id')
107
- v['@value'] = cl_node[RDF.value.to_s].first['@value']
108
- if cl_node[RDF.to_uri.to_s + 'language']
109
- lang = cl_node[RDF.to_uri.to_s + 'language'].first['@value']
110
- if lang !~ /^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$/
111
- warn "i18n datatype language must be valid BCP47: #{lang.inspect}"
106
+ # For each name and graph object in graph map:
107
+ graph_map.each do |name, graph_object|
108
+ # If rdfDirection is compound-literal, check referenced_once for entries from compound_literal_subjects
109
+ compound_literal_subjects.fetch(name, {}).each_key do |cl|
110
+ node = referenced_once[cl][:node]
111
+ next unless node.is_a?(Hash)
112
+
113
+ property = referenced_once[cl][:property]
114
+ value = referenced_once[cl][:value]
115
+ cl_node = graph_map[name].delete(cl)
116
+ next unless cl_node.is_a?(Hash)
117
+
118
+ node[property].select do |v|
119
+ next unless v['@id'] == cl
120
+
121
+ v.delete('@id')
122
+ v['@value'] = cl_node[RDF.value.to_s].first['@value']
123
+ if (langs = cl_node[RDF_LANGUAGE.to_s])
124
+ lang = langs.first['@value']
125
+ unless /^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$/.match?(lang)
126
+ warn "i18n datatype language must be valid BCP47: #{lang.inspect}"
127
+ end
128
+ v['@language'] = lang
112
129
  end
113
- v['@language'] = lang
130
+ v['@direction'] = cl_node[RDF_DIRECTION.to_s].first['@value']
114
131
  end
115
- v['@direction'] = cl_node[RDF.to_uri.to_s + 'direction'].first['@value']
116
132
  end
117
- end
118
133
 
119
- nil_var = graph_object.fetch(RDF.nil.to_s, {})
120
-
121
- # For each item usage in the usages member of nil, perform the following steps:
122
- nil_var.fetch(:usages, []).each do |usage|
123
- node, property, head = usage[:node], usage[:property], usage[:value]
124
- list, list_nodes = [], []
125
-
126
- # 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'}
128
- while property == RDF.rest.to_s &&
129
- blank_node?(node) &&
130
- referenced_once[node['@id']] &&
131
- node.keys.none? {|k| !["@id", '@type', :usages, RDF.first.to_s, RDF.rest.to_s].include?(k)} &&
132
- (f = node[RDF.first.to_s]).is_a?(Array) && f.length == 1 &&
133
- (r = node[RDF.rest.to_s]).is_a?(Array) && r.length == 1 &&
134
- ((t = node['@type']).nil? || t == [RDF.List.to_s])
135
- list << Array(node[RDF.first.to_s]).first
136
- list_nodes << node['@id']
137
-
138
- # get next node, moving backwards through list
139
- node_usage = referenced_once[node['@id']]
140
- node, property, head = node_usage[:node], node_usage[:property], node_usage[:value]
134
+ nil_var = graph_object.fetch(RDF.nil.to_s, {})
135
+
136
+ # For each item usage in the usages member of nil, perform the following steps:
137
+ nil_var.fetch(:usages, []).each do |usage|
138
+ node = usage[:node]
139
+ property = usage[:property]
140
+ head = usage[:value]
141
+ list = []
142
+ list_nodes = []
143
+
144
+ # 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:
145
+ # log_debug("list element?") {node.to_json(JSON_STATE) rescue 'malformed json'}
146
+ while property == RDF.rest.to_s &&
147
+ blank_node?(node) &&
148
+ referenced_once[node['@id']] &&
149
+ node.keys.none? { |k| !["@id", '@type', :usages, RDF.first.to_s, RDF.rest.to_s].include?(k) } &&
150
+ (f = node[RDF.first.to_s]).is_a?(Array) && f.length == 1 &&
151
+ (r = node[RDF.rest.to_s]).is_a?(Array) && r.length == 1 &&
152
+ ((t = node['@type']).nil? || t == [RDF.List.to_s])
153
+ list << Array(node[RDF.first.to_s]).first
154
+ list_nodes << node['@id']
155
+
156
+ # get next node, moving backwards through list
157
+ node_usage = referenced_once[node['@id']]
158
+ node = node_usage[:node]
159
+ property = node_usage[:property]
160
+ head = node_usage[:value]
161
+ end
162
+
163
+ head.delete('@id')
164
+ head['@list'] = list.reverse
165
+ list_nodes.each { |node_id| graph_object.delete(node_id) }
141
166
  end
142
167
 
143
- head.delete('@id')
144
- head['@list'] = list.reverse
145
- list_nodes.each {|node_id| graph_object.delete(node_id)}
168
+ # Create annotations on graph object
169
+ create_annotations(graph_object)
146
170
  end
147
171
 
148
- # Create annotations on graph object
149
- create_annotations(graph_object)
150
- end
151
-
152
- result = []
153
- default_graph.keys.opt_sort(ordered: @options[:ordered]).each do |subject|
154
- node = default_graph[subject]
155
- if graph_map.key?(subject)
156
- node['@graph'] = []
157
- graph_map[subject].keys.opt_sort(ordered: @options[:ordered]).each do |s|
158
- n = graph_map[subject][s]
159
- n.delete(:usages)
160
- node['@graph'] << n unless node_reference?(n)
172
+ result = []
173
+ default_graph.keys.opt_sort(ordered: @options[:ordered]).each do |subject|
174
+ node = default_graph[subject]
175
+ if graph_map.key?(subject)
176
+ node['@graph'] = []
177
+ graph_map[subject].keys.opt_sort(ordered: @options[:ordered]).each do |s|
178
+ n = graph_map[subject][s]
179
+ n.delete(:usages)
180
+ node['@graph'] << n unless node_reference?(n)
181
+ end
161
182
  end
183
+ node.delete(:usages)
184
+ result << node unless node_reference?(node)
162
185
  end
163
- node.delete(:usages)
164
- result << node unless node_reference?(node)
186
+ # log_debug("fromRdf") {result.to_json(JSON_STATE) rescue 'malformed json'}
187
+ result
165
188
  end
166
- #log_debug("fromRdf") {result.to_json(JSON_STATE) rescue 'malformed json'}
167
- result
168
- end
169
189
 
170
- private
171
- def resource_representation(resource, useNativeTypes)
172
- case resource
173
- when RDF::Statement
174
- # Note, if either subject or object are a BNode which is used elsewhere,
175
- # this might not work will with the BNode accounting from above.
176
- rep = {'@id' => resource_representation(resource.subject, false)}
177
- if resource.predicate == RDF.type
178
- rep['@id'].merge!('@type' => resource.object.to_s)
190
+ private
191
+
192
+ RDF_LITERAL_NATIVE_TYPES = Set.new([RDF::XSD.boolean, RDF::XSD.integer, RDF::XSD.double]).freeze
193
+
194
+ def resource_representation(resource, useNativeTypes, extendedRepresentation)
195
+ case resource
196
+ when RDF::Statement
197
+ # Note, if either subject or object are a BNode which is used elsewhere,
198
+ # this might not work will with the BNode accounting from above.
199
+ rep = { '@id' => resource_representation(resource.subject, false, extendedRepresentation) }
200
+ if resource.predicate == RDF.type
201
+ rep['@id']['@type'] = resource.object.to_s
202
+ else
203
+ rep['@id'][resource.predicate.to_s] =
204
+ as_array(resource_representation(resource.object, useNativeTypes, extendedRepresentation))
205
+ end
206
+ rep
207
+ when RDF::Literal
208
+ base = @options[:base]
209
+ rdfDirection = @options[:rdfDirection]
210
+ res = {}
211
+
212
+ if resource.datatype == RDF_JSON && @context.processingMode('json-ld-1.1')
213
+ res['@type'] = '@json'
214
+ res['@value'] = begin
215
+ ::JSON.parse(resource.object)
216
+ rescue ::JSON::ParserError => e
217
+ raise JSON::LD::JsonLdError::InvalidJsonLiteral, e.message
218
+ end
219
+ elsif useNativeTypes && extendedRepresentation
220
+ res['@value'] = resource # Raw literal
221
+ elsif resource.datatype.start_with?("https://www.w3.org/ns/i18n#") && rdfDirection == 'i18n-datatype' && @context.processingMode('json-ld-1.1')
222
+ lang, dir = resource.datatype.fragment.split('_')
223
+ res['@value'] = resource.to_s
224
+ unless lang.empty?
225
+ unless /^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$/.match?(lang)
226
+ if options[:validate]
227
+ raise JsonLdError::InvalidLanguageMapping, "rdf:language must be valid BCP47: #{lang.inspect}"
228
+ end
229
+
230
+ warn "rdf:language must be valid BCP47: #{lang.inspect}"
231
+
232
+ end
233
+ res['@language'] = lang
234
+ end
235
+ res['@direction'] = dir
236
+ elsif useNativeTypes && RDF_LITERAL_NATIVE_TYPES.include?(resource.datatype) && resource.valid?
237
+ res['@value'] = resource.object
238
+ else
239
+ resource.canonicalize! if resource.valid? && resource.datatype == RDF::XSD.double
240
+ if resource.datatype?
241
+ res['@type'] = resource.datatype.to_s
242
+ elsif resource.language?
243
+ res['@language'] = resource.language.to_s
244
+ end
245
+ res['@value'] = resource.to_s
246
+ end
247
+ res
179
248
  else
180
- rep['@id'].merge!(
181
- resource.predicate.to_s =>
182
- as_array(resource_representation(resource.object, useNativeTypes)))
249
+ { '@id' => resource.to_s }
183
250
  end
184
- rep
185
- when RDF::Literal
186
- @context.expand_value(nil,
187
- resource,
188
- rdfDirection: @options[:rdfDirection],
189
- useNativeTypes: useNativeTypes,
190
- base: @options[:base])
191
- else
192
- {'@id' => resource.to_s}
193
251
  end
194
252
  end
195
253
  end