json-ld 2.1.2 → 2.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +107 -4
- data/VERSION +1 -1
- data/lib/json/ld.rb +38 -33
- data/lib/json/ld/api.rb +27 -14
- data/lib/json/ld/compact.rb +65 -10
- data/lib/json/ld/context.rb +158 -22
- data/lib/json/ld/expand.rb +339 -279
- data/lib/json/ld/frame.rb +30 -5
- data/lib/json/ld/from_rdf.rb +4 -3
- data/spec/compact_spec.rb +1107 -328
- data/spec/context_spec.rb +153 -27
- data/spec/expand_spec.rb +907 -152
- data/spec/format_spec.rb +1 -1
- data/spec/frame_spec.rb +90 -24
- data/spec/spec_helper.rb +0 -6
- data/spec/streaming_writer_spec.rb +2 -2
- data/spec/suite_helper.rb +2 -3
- data/spec/writer_spec.rb +2 -2
- metadata +7 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2089bccb0e9e19a4f349908dd6456c908a653e9f
|
4
|
+
data.tar.gz: 97c3aef58769ce0c233d85e027fca1e0bb660fd6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 625898c1cbb1f6dbe8a2a4fce2067f6702a3205911099878d1fecaad97dd18c014ff0dcea995d90885e13fff67f04362a6b8efe1fdbad8ac7c5a62b09070c28d
|
7
|
+
data.tar.gz: 8501add1dca033f2b2c61966bf4425aeed1f1852b39b1b9dabeb2253510c56b87b70d8c480652dcc0ac4c28ef078218915554c2037c747ac939b06b65d6d4781
|
data/README.md
CHANGED
@@ -14,6 +14,8 @@ JSON::LD can now be used to create a _context_ from an RDFS/OWL definition, and
|
|
14
14
|
|
15
15
|
If the [jsonlint][] gem is installed, it will be used when validating an input document.
|
16
16
|
|
17
|
+
[Implementation Report](file.earl.html)
|
18
|
+
|
17
19
|
Install with `gem install json-ld`
|
18
20
|
|
19
21
|
### MultiJson parser
|
@@ -45,9 +47,9 @@ This gem implements an optimized streaming writer used for generating JSON-LD fr
|
|
45
47
|
JSON::LD::API.expand(input) =>
|
46
48
|
|
47
49
|
[{
|
48
|
-
"http://xmlns.com/foaf/0.1/name": ["Manu Sporny"],
|
49
|
-
"http://xmlns.com/foaf/0.1/homepage": ["http://manu.sporny.org/"],
|
50
|
-
"http://xmlns.com/foaf/0.1/avatar": ["http://twitter.com/account/profile_image/manusporny"]
|
50
|
+
"http://xmlns.com/foaf/0.1/name": [{"@value"=>"Manu Sporny"}],
|
51
|
+
"http://xmlns.com/foaf/0.1/homepage": [{"@value"=>"http://manu.sporny.org/"}],
|
52
|
+
"http://xmlns.com/foaf/0.1/avatar": [{"@value": "http://twitter.com/account/profile_image/manusporny"}]
|
51
53
|
}]
|
52
54
|
|
53
55
|
### Compact a Document
|
@@ -261,6 +263,107 @@ A context may be serialized to Ruby to speed this process using `Context#to_rb`.
|
|
261
263
|
|
262
264
|
As JSON-LD may come from many different sources, included as an embedded script tag within an HTML document, the RDF Reader will strip input before the leading `{` or `[` and after the trailing `}` or `]`.
|
263
265
|
|
266
|
+
## Extensions from JSON-LD 1.0
|
267
|
+
This implementation is being used as a test-bed for features planned for an upcoming JSON-LD 1.1 Community release.
|
268
|
+
|
269
|
+
### Scoped Contexts
|
270
|
+
A term definition can include `@context`, which is applied to values of that object. This is also used when compacting. Taken together, this allows framing to effectively include context definitions more deeply within the framed structure.
|
271
|
+
|
272
|
+
{
|
273
|
+
"@context": {
|
274
|
+
"ex": "http://example.com/",
|
275
|
+
"foo": {
|
276
|
+
"@id": "ex:foo",
|
277
|
+
"@type": "@vocab"
|
278
|
+
"@context": {
|
279
|
+
"Bar": "ex:Bar",
|
280
|
+
"Baz": "ex:Baz"
|
281
|
+
}
|
282
|
+
}
|
283
|
+
},
|
284
|
+
"foo": "Bar"
|
285
|
+
}
|
286
|
+
|
287
|
+
### @id and @type maps
|
288
|
+
The value of `@container` in a term definition can include `@id` or `@type`, in addition to `@set`, `@list`, `@language`, and `@index`. This allows value indexing based on either the `@id` or `@type` of associated objects.
|
289
|
+
|
290
|
+
{
|
291
|
+
"@context": {
|
292
|
+
"@vocab": "http://example/",
|
293
|
+
"idmap": {"@container": "@id"}
|
294
|
+
},
|
295
|
+
"idmap": {
|
296
|
+
"http://example.org/foo": {"label": "Object with @id <foo>"},
|
297
|
+
"_:bar": {"label": "Object with @id _:bar"}
|
298
|
+
}
|
299
|
+
}
|
300
|
+
|
301
|
+
### Transparent Nesting
|
302
|
+
Many JSON APIs separate properties from their entities using an intermediate object. For example, a set of possible labels may be grouped under a common property:
|
303
|
+
|
304
|
+
{
|
305
|
+
"@context": {
|
306
|
+
"skos": "http://www.w3.org/2004/02/skos/core#",
|
307
|
+
"labels": "@nest",
|
308
|
+
"main_label": {"@id": "skos:prefLabel"},
|
309
|
+
"other_label": {"@id": "skos:altLabel"},
|
310
|
+
"homepage": {"@id":"http://schema.org/description", "@type":"@id"}
|
311
|
+
},
|
312
|
+
"@id":"http://example.org/myresource",
|
313
|
+
"homepage": "http://example.org",
|
314
|
+
"labels": {
|
315
|
+
"main_label": "This is the main label for my resource",
|
316
|
+
"other_label": "This is the other label"
|
317
|
+
}
|
318
|
+
}
|
319
|
+
|
320
|
+
In this case, the `labels` property is semantically meaningless. Defining it as equivalent to `@nest` causes it to be ignored when expanding, making it equivalent to the following:
|
321
|
+
|
322
|
+
{
|
323
|
+
"@context": {
|
324
|
+
"skos": "http://www.w3.org/2004/02/skos/core#",
|
325
|
+
"labels": "@nest",
|
326
|
+
"main_label": {"@id": "skos:prefLabel"},
|
327
|
+
"other_label": {"@id": "skos:altLabel"},
|
328
|
+
"homepage": {"@id":"http://schema.org/description", "@type":"@id"}
|
329
|
+
},
|
330
|
+
"@id":"http://example.org/myresource",
|
331
|
+
"homepage": "http://example.org",
|
332
|
+
"main_label": "This is the main label for my resource",
|
333
|
+
"other_label": "This is the other label"
|
334
|
+
}
|
335
|
+
|
336
|
+
Similarly, properties may be marked with "@nest": "nest-term", to cause them to be nested. Note that the `@nest` keyword can also be aliased in the context.
|
337
|
+
|
338
|
+
{
|
339
|
+
"@context": {
|
340
|
+
"skos": "http://www.w3.org/2004/02/skos/core#",
|
341
|
+
"labels": "@nest",
|
342
|
+
"main_label": {"@id": "skos:prefLabel", "@nest": "labels"},
|
343
|
+
"other_label": {"@id": "skos:altLabel", "@nest": "labels"},
|
344
|
+
"homepage": {"@id":"http://schema.org/description", "@type":"@id"}
|
345
|
+
},
|
346
|
+
"@id":"http://example.org/myresource",
|
347
|
+
"homepage": "http://example.org",
|
348
|
+
"labels": {
|
349
|
+
"main_label": "This is the main label for my resource",
|
350
|
+
"other_label": "This is the other label"
|
351
|
+
}
|
352
|
+
}
|
353
|
+
|
354
|
+
In this way, nesting survives round-tripping through expansion, and framed output can include nested properties.
|
355
|
+
|
356
|
+
### Framing Updates
|
357
|
+
The [JSON-LD Framing 1.1 Specification]() improves on previous un-released versions.
|
358
|
+
|
359
|
+
* [More Specific Frame matching](https://github.com/json-ld/json-ld.org/issues/110) – Allows framing to extend to elements of value objects, and objects are matched through recursive frame matching. `{}` is used as a wildcard, and `[]` as matching nothing.
|
360
|
+
* [Graph framing](https://github.com/json-ld/json-ld.org/issues/118) – previously, only the merged graph can be framed, this update allows arbitrary graphs to be framed.
|
361
|
+
* Use `@graph` in frame, matches the default graph, not the merged graph.
|
362
|
+
* Use `@graph` in property value, causes the apropriatly named graph to be used for filling in values.
|
363
|
+
* [Reverse properties](https://github.com/json-ld/json-ld.org/issues/311) – `@reverse` (or a property defined with `@reverse`) can cause matching values to be included, allowing a matched object to include reverse references to any objects referencing it.
|
364
|
+
* [@omitDefault behavior](https://github.com/json-ld/json-ld.org/issues/389) – In addition to `true` and `false`, `@omitDefault` can take `@last`, `@always`, `@never`, and `@link`.
|
365
|
+
* [multiple `@id` matching](https://github.com/json-ld/json-ld.org/issues/424) – A frame can match based on one or more specific object `@id` values.
|
366
|
+
|
264
367
|
## Documentation
|
265
368
|
Full documentation available on [RubyDoc](http://rubydoc.info/gems/json-ld/file/README.md)
|
266
369
|
|
@@ -286,7 +389,7 @@ Note, the API method signatures differed in versions before 1.0, in that they al
|
|
286
389
|
|
287
390
|
## Dependencies
|
288
391
|
* [Ruby](http://ruby-lang.org/) (>= 2.2.2)
|
289
|
-
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.
|
392
|
+
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.2)
|
290
393
|
* [JSON](https://rubygems.org/gems/json) (>= 1.5)
|
291
394
|
|
292
395
|
## Installation
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.
|
1
|
+
2.1.3
|
data/lib/json/ld.rb
CHANGED
@@ -34,7 +34,7 @@ module JSON
|
|
34
34
|
autoload :Resource, 'json/ld/resource'
|
35
35
|
autoload :VERSION, 'json/ld/version'
|
36
36
|
autoload :Writer, 'json/ld/writer'
|
37
|
-
|
37
|
+
|
38
38
|
# Initial context
|
39
39
|
# @see http://json-ld.org/spec/latest/json-ld-api/#appendix-b
|
40
40
|
INITIAL_CONTEXT = {
|
@@ -53,12 +53,14 @@ module JSON
|
|
53
53
|
@graph
|
54
54
|
@language
|
55
55
|
@list
|
56
|
+
@nest
|
56
57
|
@omitDefault
|
57
58
|
@requireAll
|
58
59
|
@reverse
|
59
60
|
@set
|
60
61
|
@type
|
61
62
|
@value
|
63
|
+
@version
|
62
64
|
@vocab
|
63
65
|
).freeze
|
64
66
|
|
@@ -87,7 +89,7 @@ module JSON
|
|
87
89
|
array_nl: "\n"
|
88
90
|
)
|
89
91
|
|
90
|
-
class JsonLdError <
|
92
|
+
class JsonLdError < StandardError
|
91
93
|
def to_s
|
92
94
|
"#{self.class.instance_variable_get :@code}: #{super}"
|
93
95
|
end
|
@@ -95,46 +97,49 @@ module JSON
|
|
95
97
|
self.class.instance_variable_get :@code
|
96
98
|
end
|
97
99
|
|
98
|
-
class
|
99
|
-
class
|
100
|
-
class InvalidIndexValue < JsonLdError; @code = "invalid @index value"; end
|
100
|
+
class CollidingKeywords < JsonLdError; @code = "colliding keywords"; end
|
101
|
+
class CompactionToListOfLists < JsonLdError; @code = "compaction to list of lists"; end
|
101
102
|
class ConflictingIndexes < JsonLdError; @code = "conflicting indexes"; end
|
102
|
-
class
|
103
|
-
class InvalidLocalContext < JsonLdError; @code = "invalid local context"; end
|
104
|
-
class MultipleContextLinkHeaders < JsonLdError; @code = "multiple context link headers"; end
|
105
|
-
class LoadingRemoteContextFailed < JsonLdError; @code = "loading remote context failed"; end
|
106
|
-
class InvalidRemoteContext < JsonLdError; @code = "invalid remote context"; end
|
107
|
-
class RecursiveContextInclusion < JsonLdError; @code = "recursive context inclusion"; end
|
103
|
+
class CyclicIRIMapping < JsonLdError; @code = "cyclic IRI mapping"; end
|
108
104
|
class InvalidBaseIRI < JsonLdError; @code = "invalid base IRI"; end
|
109
|
-
class
|
105
|
+
class InvalidContainerMapping < JsonLdError; @code = "invalid container mapping"; end
|
110
106
|
class InvalidDefaultLanguage < JsonLdError; @code = "invalid default language"; end
|
111
|
-
class
|
112
|
-
class
|
113
|
-
class
|
107
|
+
class InvalidIdValue < JsonLdError; @code = "invalid @id value"; end
|
108
|
+
class InvalidIndexValue < JsonLdError; @code = "invalid @index value"; end
|
109
|
+
class InvalidVersionValue < JsonLdError; @code = "invalid @version value"; end
|
114
110
|
class InvalidIRIMapping < JsonLdError; @code = "invalid IRI mapping"; end
|
115
|
-
class CyclicIRIMapping < JsonLdError; @code = "cyclic IRI mapping"; end
|
116
111
|
class InvalidKeywordAlias < JsonLdError; @code = "invalid keyword alias"; end
|
117
|
-
class InvalidTypeMapping < JsonLdError; @code = "invalid type mapping"; end
|
118
112
|
class InvalidLanguageMapping < JsonLdError; @code = "invalid language mapping"; end
|
119
|
-
class
|
120
|
-
class InvalidContainerMapping < JsonLdError; @code = "invalid container mapping"; end
|
121
|
-
class InvalidTypeValue < JsonLdError; @code = "invalid type value"; end
|
122
|
-
class InvalidValueObject < JsonLdError; @code = "invalid value object"; end
|
123
|
-
class InvalidValueObjectValue < JsonLdError; @code = "invalid value object value"; end
|
113
|
+
class InvalidLanguageMapValue < JsonLdError; @code = "invalid language map value"; end
|
124
114
|
class InvalidLanguageTaggedString < JsonLdError; @code = "invalid language-tagged string"; end
|
125
115
|
class InvalidLanguageTaggedValue < JsonLdError; @code = "invalid language-tagged value"; end
|
126
|
-
class
|
127
|
-
class
|
128
|
-
class
|
129
|
-
class
|
116
|
+
class InvalidLocalContext < JsonLdError; @code = "invalid local context"; end
|
117
|
+
class InvalidNestValue < JsonLdError; @code = "invalid @nest value"; end
|
118
|
+
class InvalidRemoteContext < JsonLdError; @code = "invalid remote context"; end
|
119
|
+
class InvalidReverseProperty < JsonLdError; @code = "invalid reverse property"; end
|
130
120
|
class InvalidReversePropertyMap < JsonLdError; @code = "invalid reverse property map"; end
|
131
|
-
class InvalidReverseValue < JsonLdError; @code = "invalid @reverse value"; end
|
132
121
|
class InvalidReversePropertyValue < JsonLdError; @code = "invalid reverse property value"; end
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
class
|
137
|
-
class
|
122
|
+
class InvalidReverseValue < JsonLdError; @code = "invalid @reverse value"; end
|
123
|
+
class InvalidScopedContext < JsonLdError; @code = "invalid scoped context"; end
|
124
|
+
class InvalidSetOrListObject < JsonLdError; @code = "invalid set or list object"; end
|
125
|
+
class InvalidTermDefinition < JsonLdError; @code = "invalid term definition"; end
|
126
|
+
class InvalidTypedValue < JsonLdError; @code = "invalid typed value"; end
|
127
|
+
class InvalidTypeMapping < JsonLdError; @code = "invalid type mapping"; end
|
128
|
+
class InvalidTypeValue < JsonLdError; @code = "invalid type value"; end
|
129
|
+
class InvalidValueObject < JsonLdError; @code = "invalid value object"; end
|
130
|
+
class InvalidValueObjectValue < JsonLdError; @code = "invalid value object value"; end
|
131
|
+
class InvalidVocabMapping < JsonLdError; @code = "invalid vocab mapping"; end
|
132
|
+
class KeywordRedefinition < JsonLdError; @code = "keyword redefinition"; end
|
133
|
+
class ListOfLists < JsonLdError; @code = "list of lists"; end
|
134
|
+
class LoadingDocumentFailed < JsonLdError; @code = "loading document failed"; end
|
135
|
+
class LoadingRemoteContextFailed < JsonLdError; @code = "loading remote context failed"; end
|
136
|
+
class MultipleContextLinkHeaders < JsonLdError; @code = "multiple context link headers"; end
|
137
|
+
class ProcessingModeConflict < JsonLdError; @code = "processing mode conflict"; end
|
138
|
+
class RecursiveContextInclusion < JsonLdError; @code = "recursive context inclusion"; end
|
139
|
+
class InvalidFrame < JsonLdError
|
140
|
+
class MultipleEmbeds < InvalidFrame; end
|
141
|
+
class Syntax < InvalidFrame; end
|
142
|
+
end
|
138
143
|
end
|
139
144
|
end
|
140
|
-
end
|
145
|
+
end
|
data/lib/json/ld/api.rb
CHANGED
@@ -69,10 +69,12 @@ module JSON::LD
|
|
69
69
|
# A context that is used to initialize the active context when expanding a document.
|
70
70
|
# @option options [Boolean, String, RDF::URI] :flatten
|
71
71
|
# If set to a value that is not `false`, the JSON-LD processor must modify the output of the Compaction Algorithm or the Expansion Algorithm by coalescing all properties associated with each subject via the Flattening Algorithm. The value of `flatten must` be either an _IRI_ value representing the name of the graph to flatten, or `true`. If the value is `true`, then the first graph encountered in the input document is selected and flattened.
|
72
|
-
# @option options [String] :processingMode
|
72
|
+
# @option options [String] :processingMode
|
73
73
|
# Processing mode, json-ld-1.0 or json-ld-1.1. Also can have other values:
|
74
74
|
#
|
75
75
|
# * json-ld-1.1-expand-frame – special frame expansion mode.
|
76
|
+
#
|
77
|
+
# If `processingMode` is not specified, a mode of `json-ld-1.0` or `json-ld-1.1` is set, the context used for `expansion` or `compaction`.
|
76
78
|
# @option options [Boolean] :rename_bnodes (true)
|
77
79
|
# Rename bnodes as part of expansion, or keep them the same.
|
78
80
|
# @option options [Boolean] :unique_bnodes (false)
|
@@ -88,10 +90,8 @@ module JSON::LD
|
|
88
90
|
@options = {
|
89
91
|
compactArrays: true,
|
90
92
|
rename_bnodes: true,
|
91
|
-
processingMode: "json-ld-1.1",
|
92
93
|
documentLoader: self.class.method(:documentLoader)
|
93
94
|
}
|
94
|
-
@options[:validate] = %w(json-ld-1.0 json-ld-1.1).include?(@options[:processingMode])
|
95
95
|
@options = @options.merge(options)
|
96
96
|
@namer = options[:unique_bnodes] ? BlankNodeUniqer.new : (@options[:rename_bnodes] ? BlankNodeNamer.new("b") : BlankNodeMapper.new)
|
97
97
|
|
@@ -135,6 +135,10 @@ module JSON::LD
|
|
135
135
|
context ||= (@value['@context'] if @value.is_a?(Hash)) || context_ref
|
136
136
|
@context = Context.parse(context || {}, @options)
|
137
137
|
|
138
|
+
# If not set explicitly, the context figures out the processing mode
|
139
|
+
@options[:processingMode] ||= @context.processingMode
|
140
|
+
@options[:validate] ||= %w(json-ld-1.0 json-ld-1.1).include?(@options[:processingMode])
|
141
|
+
|
138
142
|
if block_given?
|
139
143
|
case block.arity
|
140
144
|
when 0, -1 then instance_eval(&block)
|
@@ -207,7 +211,7 @@ module JSON::LD
|
|
207
211
|
expanded_input = options[:expanded] ? input : API.expand(input, options)
|
208
212
|
|
209
213
|
API.new(expanded_input, context, options) do
|
210
|
-
log_debug(".compact") {"expanded input: #{
|
214
|
+
log_debug(".compact") {"expanded input: #{expanded_input.to_json(JSON_STATE) rescue 'malformed json'}"}
|
211
215
|
result = compact(value)
|
212
216
|
|
213
217
|
# xxx) Add the given context to the output
|
@@ -298,6 +302,7 @@ module JSON::LD
|
|
298
302
|
# @option options [Boolean] :omitDefault (false)
|
299
303
|
# a flag specifying that properties that are missing from the JSON-LD input should be omitted from the output.
|
300
304
|
# @option options [Boolean] :expanded Input is already expanded
|
305
|
+
# @option options [Boolean] :pruneBlankNodeIdentifiers (true) removes blank node identifiers that are only used once.
|
301
306
|
# @yield jsonld
|
302
307
|
# @yieldparam [Hash] jsonld
|
303
308
|
# The framed JSON-LD document
|
@@ -309,13 +314,14 @@ module JSON::LD
|
|
309
314
|
def self.frame(input, frame, options = {})
|
310
315
|
result = nil
|
311
316
|
options = {
|
312
|
-
base:
|
313
|
-
compactArrays:
|
314
|
-
embed:
|
315
|
-
explicit:
|
316
|
-
requireAll:
|
317
|
-
omitDefault:
|
318
|
-
|
317
|
+
base: (input if input.is_a?(String)),
|
318
|
+
compactArrays: true,
|
319
|
+
embed: '@last',
|
320
|
+
explicit: false,
|
321
|
+
requireAll: true,
|
322
|
+
omitDefault: false,
|
323
|
+
pruneBlankNodeIdentifiers: true,
|
324
|
+
documentLoader: method(:documentLoader)
|
319
325
|
}.merge!(options)
|
320
326
|
|
321
327
|
framing_state = {
|
@@ -365,7 +371,12 @@ module JSON::LD
|
|
365
371
|
|
366
372
|
result = []
|
367
373
|
frame(framing_state, framing_state[:subjects].keys.sort, (expanded_frame.first || {}), options.merge(parent: result))
|
368
|
-
|
374
|
+
|
375
|
+
# Count blank node identifiers used in the document, if pruning
|
376
|
+
bnodes_to_clear = if options[:pruneBlankNodeIdentifiers]
|
377
|
+
count_blank_node_identifiers(result).collect {|k, v| k if v == 1}.compact
|
378
|
+
end
|
379
|
+
|
369
380
|
# Initalize context from frame
|
370
381
|
@context = @context.parse(frame['@context'])
|
371
382
|
# Compact result
|
@@ -376,7 +387,7 @@ module JSON::LD
|
|
376
387
|
kwgraph = context.compact_iri('@graph', quiet: true)
|
377
388
|
result = context.serialize.merge({kwgraph => compacted})
|
378
389
|
log_debug(".frame") {"after compact: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}
|
379
|
-
result = cleanup_preserve(result)
|
390
|
+
result = cleanup_preserve(result, bnodes_to_clear || [])
|
380
391
|
end
|
381
392
|
|
382
393
|
block_given? ? yield(result) : result
|
@@ -450,6 +461,7 @@ module JSON::LD
|
|
450
461
|
# @option options (see #initialize)
|
451
462
|
# @option options [Boolean] :useRdfType (false)
|
452
463
|
# If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
|
464
|
+
# @option options [Boolean] :useNativeTypes (false) use native representations
|
453
465
|
# @yield jsonld
|
454
466
|
# @yieldparam [Hash] jsonld
|
455
467
|
# The JSON-LD document in expanded form
|
@@ -458,10 +470,11 @@ module JSON::LD
|
|
458
470
|
# If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
|
459
471
|
def self.fromRdf(input, options = {}, &block)
|
460
472
|
useRdfType = options.fetch(:useRdfType, false)
|
473
|
+
useNativeTypes = options.fetch(:useNativeTypes, false)
|
461
474
|
result = nil
|
462
475
|
|
463
476
|
API.new(nil, nil, options) do |api|
|
464
|
-
result = api.from_statements(input, useRdfType: useRdfType)
|
477
|
+
result = api.from_statements(input, useRdfType: useRdfType, useNativeTypes: useNativeTypes)
|
465
478
|
end
|
466
479
|
|
467
480
|
block_given? ? yield(result) : result
|
data/lib/json/ld/compact.rb
CHANGED
@@ -16,6 +16,12 @@ module JSON::LD
|
|
16
16
|
#else
|
17
17
|
# log_debug("compact") {"property: #{property.inspect}"}
|
18
18
|
#end
|
19
|
+
|
20
|
+
# If the term definition for active property itself contains a context, use that for compacting values.
|
21
|
+
input_context = self.context
|
22
|
+
td = self.context.term_definitions[property] if property
|
23
|
+
self.context = (td && td.context && self.context.parse(td.context)) || input_context
|
24
|
+
|
19
25
|
case element
|
20
26
|
when Array
|
21
27
|
#log_debug("") {"Array #{element.inspect}"}
|
@@ -46,9 +52,9 @@ module JSON::LD
|
|
46
52
|
end
|
47
53
|
|
48
54
|
inside_reverse = property == '@reverse'
|
49
|
-
result = {}
|
55
|
+
result, nest_result = {}, nil
|
50
56
|
|
51
|
-
element.
|
57
|
+
element.keys.sort.each do |expanded_property|
|
52
58
|
expanded_value = element[expanded_property]
|
53
59
|
#log_debug("") {"#{expanded_property}: #{expanded_value.inspect}"}
|
54
60
|
|
@@ -56,6 +62,15 @@ module JSON::LD
|
|
56
62
|
compacted_value = [expanded_value].flatten.compact.map do |expanded_type|
|
57
63
|
context.compact_iri(expanded_type, vocab: (expanded_property == '@type'), log_depth: @options[:log_depth])
|
58
64
|
end
|
65
|
+
|
66
|
+
# If key is @type and any compacted value is a term having a local context, overlay that context.
|
67
|
+
if expanded_property == '@type'
|
68
|
+
compacted_value.each do |term|
|
69
|
+
term_context = self.context.term_definitions[term].context if context.term_definitions[term]
|
70
|
+
self.context = context.parse(term_context) if term_context
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
59
74
|
compacted_value = compacted_value.first if compacted_value.length == 1
|
60
75
|
|
61
76
|
al = context.compact_iri(expanded_property, vocab: true, quiet: true)
|
@@ -72,6 +87,7 @@ module JSON::LD
|
|
72
87
|
value = [value] if !value.is_a?(Array) &&
|
73
88
|
(context.container(prop) == '@set' || !@options[:compactArrays])
|
74
89
|
#log_debug("") {"merge #{prop} => #{value.inspect}"}
|
90
|
+
|
75
91
|
merge_compacted_value(result, prop, value)
|
76
92
|
compacted_value.delete(prop)
|
77
93
|
end
|
@@ -106,8 +122,14 @@ module JSON::LD
|
|
106
122
|
reverse: inside_reverse,
|
107
123
|
log_depth: @options[:log_depth])
|
108
124
|
|
109
|
-
|
110
|
-
|
125
|
+
if nest_prop = context.nest(item_active_property)
|
126
|
+
result[nest_prop] ||= {}
|
127
|
+
iap = result[result[nest_prop]] ||= []
|
128
|
+
result[nest_prop][item_active_property] = [iap] unless iap.is_a?(Array)
|
129
|
+
else
|
130
|
+
iap = result[item_active_property] ||= []
|
131
|
+
result[item_active_property] = [iap] unless iap.is_a?(Array)
|
132
|
+
end
|
111
133
|
end
|
112
134
|
|
113
135
|
# At this point, expanded value must be an array due to the Expansion algorithm.
|
@@ -119,6 +141,14 @@ module JSON::LD
|
|
119
141
|
reverse: inside_reverse,
|
120
142
|
log_depth: @options[:log_depth])
|
121
143
|
|
144
|
+
|
145
|
+
nest_result = if nest_prop = context.nest(item_active_property)
|
146
|
+
# FIXME??: It's possible that nest_prop will be used both for nesting, and for values of @nest
|
147
|
+
result[nest_prop] ||= {}
|
148
|
+
else
|
149
|
+
result
|
150
|
+
end
|
151
|
+
|
122
152
|
container = context.container(item_active_property)
|
123
153
|
value = list?(expanded_item) ? expanded_item['@list'] : expanded_item
|
124
154
|
compacted_item = compact(value, property: item_active_property)
|
@@ -135,14 +165,36 @@ module JSON::LD
|
|
135
165
|
end
|
136
166
|
else
|
137
167
|
raise JsonLdError::CompactionToListOfLists,
|
138
|
-
"key cannot have more than one list value" if
|
168
|
+
"key cannot have more than one list value" if nest_result.has_key?(item_active_property)
|
139
169
|
end
|
140
170
|
end
|
141
171
|
|
142
|
-
if %w(@language @index).include?(container)
|
143
|
-
map_object =
|
144
|
-
compacted_item =
|
145
|
-
|
172
|
+
if %w(@language @index @id @type).include?(container)
|
173
|
+
map_object = nest_result[item_active_property] ||= {}
|
174
|
+
compacted_item = case container
|
175
|
+
when '@id'
|
176
|
+
id_prop = context.compact_iri('@id', vocab: true, quiet: true)
|
177
|
+
map_key = compacted_item[id_prop]
|
178
|
+
map_key = context.compact_iri(map_key, quiet: true)
|
179
|
+
compacted_item.delete(id_prop)
|
180
|
+
compacted_item
|
181
|
+
when '@index'
|
182
|
+
map_key = expanded_item[container]
|
183
|
+
compacted_item
|
184
|
+
when '@language'
|
185
|
+
map_key = expanded_item[container]
|
186
|
+
value?(expanded_item) ? expanded_item['@value'] : compacted_item
|
187
|
+
when '@type'
|
188
|
+
type_prop = context.compact_iri('@type', vocab: true, quiet: true)
|
189
|
+
map_key, *types = Array(compacted_item[type_prop])
|
190
|
+
map_key = context.compact_iri(map_key, vocab: true, quiet: true)
|
191
|
+
case types.length
|
192
|
+
when 0 then compacted_item.delete(type_prop)
|
193
|
+
when 1 then compacted_item[type_prop] = types.first
|
194
|
+
else compacted_item[type_prop] = types
|
195
|
+
end
|
196
|
+
compacted_item
|
197
|
+
end
|
146
198
|
merge_compacted_value(map_object, map_key, compacted_item)
|
147
199
|
else
|
148
200
|
compacted_item = [compacted_item] if
|
@@ -151,7 +203,7 @@ module JSON::LD
|
|
151
203
|
%w(@set @list).include?(container) ||
|
152
204
|
%w(@list @graph).include?(expanded_property)
|
153
205
|
)
|
154
|
-
merge_compacted_value(
|
206
|
+
merge_compacted_value(nest_result, item_active_property, compacted_item)
|
155
207
|
end
|
156
208
|
end
|
157
209
|
end
|
@@ -163,6 +215,9 @@ module JSON::LD
|
|
163
215
|
#log_debug("compact") {element.class.to_s}
|
164
216
|
element
|
165
217
|
end
|
218
|
+
|
219
|
+
ensure
|
220
|
+
self.context = input_context
|
166
221
|
end
|
167
222
|
end
|
168
223
|
end
|