json-ld 3.2.4 → 3.3.0

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