json-ld 3.2.1 → 3.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -5
  3. data/VERSION +1 -1
  4. data/lib/json/ld/api.rb +53 -16
  5. data/lib/json/ld/reader.rb +1 -1
  6. data/lib/json/ld/streaming_reader.rb +2 -1
  7. data/lib/json/ld/to_rdf.rb +1 -1
  8. data/lib/json/ld/writer.rb +8 -9
  9. data/lib/json/ld.rb +3 -0
  10. data/spec/api_spec.rb +67 -19
  11. data/spec/format_spec.rb +2 -2
  12. data/spec/frame_spec.rb +25 -1
  13. data/spec/suite_helper.rb +1 -0
  14. data/spec/test-files/{test-1-compacted.json → test-1-compacted.jsonld} +0 -0
  15. data/spec/test-files/{test-1-context.json → test-1-context.jsonld} +0 -0
  16. data/spec/test-files/{test-1-expanded.json → test-1-expanded.jsonld} +0 -0
  17. data/spec/test-files/{test-1-input.json → test-1-input.jsonld} +0 -0
  18. data/spec/test-files/{test-2-compacted.json → test-2-compacted.jsonld} +0 -0
  19. data/spec/test-files/{test-2-context.json → test-2-context.jsonld} +0 -0
  20. data/spec/test-files/{test-2-expanded.json → test-2-expanded.jsonld} +0 -0
  21. data/spec/test-files/{test-2-input.json → test-2-input.jsonld} +0 -0
  22. data/spec/test-files/{test-3-compacted.json → test-3-compacted.jsonld} +0 -0
  23. data/spec/test-files/{test-3-context.json → test-3-context.jsonld} +0 -0
  24. data/spec/test-files/{test-3-expanded.json → test-3-expanded.jsonld} +0 -0
  25. data/spec/test-files/{test-3-input.json → test-3-input.jsonld} +0 -0
  26. data/spec/test-files/{test-4-compacted.json → test-4-compacted.jsonld} +0 -0
  27. data/spec/test-files/{test-4-context.json → test-4-context.jsonld} +0 -0
  28. data/spec/test-files/{test-4-expanded.json → test-4-expanded.jsonld} +0 -0
  29. data/spec/test-files/{test-4-input.json → test-4-input.jsonld} +0 -0
  30. data/spec/test-files/{test-5-compacted.json → test-5-compacted.jsonld} +0 -0
  31. data/spec/test-files/{test-5-context.json → test-5-context.jsonld} +0 -0
  32. data/spec/test-files/{test-5-expanded.json → test-5-expanded.jsonld} +0 -0
  33. data/spec/test-files/{test-5-input.json → test-5-input.jsonld} +0 -0
  34. data/spec/test-files/{test-6-compacted.json → test-6-compacted.jsonld} +0 -0
  35. data/spec/test-files/{test-6-context.json → test-6-context.jsonld} +0 -0
  36. data/spec/test-files/{test-6-expanded.json → test-6-expanded.jsonld} +0 -0
  37. data/spec/test-files/{test-6-input.json → test-6-input.jsonld} +0 -0
  38. data/spec/test-files/{test-7-compacted.json → test-7-compacted.jsonld} +0 -0
  39. data/spec/test-files/{test-7-context.json → test-7-context.jsonld} +0 -0
  40. data/spec/test-files/{test-7-expanded.json → test-7-expanded.jsonld} +0 -0
  41. data/spec/test-files/{test-7-input.json → test-7-input.jsonld} +0 -0
  42. data/spec/test-files/{test-8-compacted.json → test-8-compacted.jsonld} +0 -0
  43. data/spec/test-files/{test-8-context.json → test-8-context.jsonld} +0 -0
  44. data/spec/test-files/{test-8-expanded.json → test-8-expanded.jsonld} +0 -0
  45. data/spec/test-files/{test-8-frame.json → test-8-frame.jsonld} +0 -0
  46. data/spec/test-files/{test-8-framed.json → test-8-framed.jsonld} +0 -0
  47. data/spec/test-files/{test-8-input.json → test-8-input.jsonld} +0 -0
  48. data/spec/test-files/{test-9-compacted.json → test-9-compacted.jsonld} +0 -0
  49. data/spec/test-files/{test-9-context.json → test-9-context.jsonld} +0 -0
  50. data/spec/test-files/{test-9-expanded.json → test-9-expanded.jsonld} +0 -0
  51. data/spec/test-files/{test-9-input.json → test-9-input.jsonld} +0 -0
  52. metadata +78 -84
  53. data/spec/test-files/test-1-normalized.json +0 -8
  54. data/spec/test-files/test-2-normalized.json +0 -32
  55. data/spec/test-files/test-3-normalized.json +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54bba5db6d794f8e36e96200fb75cce4377021ea02c008bcc09b76a4a6ff95a2
4
- data.tar.gz: bbd5282a8f1b87d6c44b567a49135f32765f11ada771fffd5e26683481589a19
3
+ metadata.gz: 63c237710b5f32fe8037a11969feaf712a79f68a4d1d568a89ece1a5d1d26ff2
4
+ data.tar.gz: cac81da94266cac30a7e31e5018477ef55e52b6b1701b048214947f266439236
5
5
  SHA512:
6
- metadata.gz: 7f13bf980c40f0aa82965c6cd6ee9fe5f8c63d91b5206974630d5bfd84ebf9318902654e8937644ef79aa02f1447c41cc3c3ea4382998b74b275f80ebff00f93
7
- data.tar.gz: 36a5a219f342d13249f1c6a3971448b9dea645640f5bc55d21278b831c3c619d584ad2dda27cee94793b5bd3954c5a0e54507ea6c99a328a3da7feb19730058a
6
+ metadata.gz: 440da082cc1cbabcd69e8cb3d34858c4fe8fd96b116c0d67651d5ce7338d6e787f9d00451ff1f730d08982f0d8697d097f51d09d033ff7f8e290252006f96c78
7
+ data.tar.gz: 0b877d9d96857964a4913aef1790aa04dc98f83676ec0154c016ad05e7a9dc0a22b1b3bd31ae785cfb4447ac6914291ac56d42f5dc6781fc58c6687ccd4d15cd
data/README.md CHANGED
@@ -32,10 +32,10 @@ This gem also implements an optimized streaming writer used for generating JSON-
32
32
  * Each statement written as a separate node in expanded/flattened form.
33
33
  * `RDF List`s are written as separate nodes using `rdf:first` and `rdf:rest` properties.
34
34
 
35
- The order of triples retrieved from the `RDF::Enumerable` dataset determines the way that JSON-LD node objects are written; for best results, statements should be ordered by _graph name_, _subect_, _predicate_ and _object_.
35
+ The order of triples retrieved from the `RDF::Enumerable` dataset determines the way that JSON-LD node objects are written; for best results, statements should be ordered by _graph name_, _subject_, _predicate_ and _object_.
36
36
 
37
37
  ### MultiJson parser
38
- The [MultiJson](https://rubygems.org/gems/multi_json) gem is used for parsing JSON; this defaults to the native JSON parser, but will use a more performant parser if one is available. A specific parser can be specified by adding the `:adapter` option to any API call. See [MultiJson](https://rubygems.org/gems/multi_json) for more information.
38
+ The [MultiJson](https://rubygems.org/gems/multi_json) gem is used for parsing and serializing JSON; this defaults to the native JSON parser/serializer, but will use a more performant parser if one is available. A specific parser can be specified by adding the `:adapter` option to any API call. Additionally, a custom serialilzer may be specified by passing the `:serializer` option to {JSON::LD::Writer} or methods of {JSON::LD::API}. See [MultiJson](https://rubygems.org/gems/multi_json) for more information.
39
39
 
40
40
  ### JSON-LD-star (RDFStar)
41
41
 
@@ -624,8 +624,7 @@ To get a local working copy of the development repository, do:
624
624
  which you will be asked to agree to on the first commit to a repo within the organization.
625
625
  Note that the agreement applies to all repos in the [Ruby RDF](https://github.com/ruby-rdf/) organization.
626
626
 
627
- License
628
- -------
627
+ ## License
629
628
 
630
629
  This is free and unencumbered public domain software. For more information,
631
630
  see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
@@ -641,7 +640,7 @@ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
641
640
  [Backports]: https://rubygems.org/gems/backports
642
641
  [JSON-LD]: https://www.w3.org/TR/json-ld11/ "JSON-LD 1.1"
643
642
  [JSON-LD API]: https://www.w3.org/TR/json-ld11-api/ "JSON-LD 1.1 Processing Algorithms and API"
644
- [JSON-LD Framing]: https://www.w3.org/TR/json-ld11-framing/ "JSON-LD Framing 1.1"
643
+ [JSON-LD Framing]: https://www.w3.org/TR/json-ld11-framing/ "JSON-LD 1.1 Framing"
645
644
  [Promises]: https://dom.spec.whatwg.org/#promises
646
645
  [jsonlint]: https://rubygems.org/gems/jsonlint
647
646
  [Sinatra]: https://www.sinatrarb.com/
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.1
1
+ 3.2.2
data/lib/json/ld/api.rb CHANGED
@@ -126,7 +126,8 @@ module JSON::LD
126
126
 
127
127
  case remote_doc.document
128
128
  when String
129
- MultiJson.load(remote_doc.document, **options)
129
+ mj_opts = options.keep_if {|k,v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v)}
130
+ MultiJson.load(remote_doc.document, **mj_opts)
130
131
  else
131
132
  # Already parsed
132
133
  remote_doc.document
@@ -155,6 +156,9 @@ module JSON::LD
155
156
  #
156
157
  # @param [String, #read, Hash, Array] input
157
158
  # The JSON-LD object to copy and perform the expansion upon.
159
+ # @param [Proc] serializer (nil)
160
+ # A Serializer method used for generating the JSON serialization of the result. If absent, the internal Ruby objects are returned, which can be transformed to JSON externally via `#to_json`.
161
+ # See {JSON::LD::API.serializer}.
158
162
  # @param [Hash{Symbol => Object}] options
159
163
  # @option options (see #initialize)
160
164
  # @raise [JsonLdError]
@@ -167,7 +171,7 @@ module JSON::LD
167
171
  # @return [Object, Array<Hash>]
168
172
  # If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
169
173
  # @see https://www.w3.org/TR/json-ld11-api/#expansion-algorithm
170
- def self.expand(input, framing: false, **options, &block)
174
+ def self.expand(input, framing: false, serializer: nil, **options, &block)
171
175
  result = doc_base = nil
172
176
  API.new(input, options[:expandContext], **options) do
173
177
  result = self.expand(self.value, nil, self.context,
@@ -180,6 +184,7 @@ module JSON::LD
180
184
 
181
185
  # Finally, if element is a JSON object, it is wrapped into an array.
182
186
  result = [result].compact unless result.is_a?(Array)
187
+ result = serializer.call(result, **options) if serializer
183
188
 
184
189
  if block_given?
185
190
  case block.arity
@@ -204,6 +209,9 @@ module JSON::LD
204
209
  # The JSON-LD object to copy and perform the compaction upon.
205
210
  # @param [String, #read, Hash, Array, JSON::LD::Context] context
206
211
  # The base context to use when compacting the input.
212
+ # @param [Proc] serializer (nil)
213
+ # A Serializer instance used for generating the JSON serialization of the result. If absent, the internal Ruby objects are returned, which can be transformed to JSON externally via `#to_json`.
214
+ # See {JSON::LD::API.serializer}.
207
215
  # @param [Boolean] expanded (false) Input is already expanded
208
216
  # @param [Hash{Symbol => Object}] options
209
217
  # @option options (see #initialize)
@@ -215,7 +223,7 @@ module JSON::LD
215
223
  # If a block is given, the result of evaluating the block is returned, otherwise, the compacted JSON-LD document
216
224
  # @raise [JsonLdError]
217
225
  # @see https://www.w3.org/TR/json-ld11-api/#compaction-algorithm
218
- def self.compact(input, context, expanded: false, **options)
226
+ def self.compact(input, context, expanded: false, serializer: nil, **options)
219
227
  result = nil
220
228
  options = {compactToRelative: true}.merge(options)
221
229
 
@@ -238,6 +246,7 @@ module JSON::LD
238
246
  end
239
247
  result = ctx.merge(result) unless ctx.fetch('@context', {}).empty?
240
248
  end
249
+ result = serializer.call(result, **options) if serializer
241
250
  block_given? ? yield(result) : result
242
251
  end
243
252
 
@@ -251,6 +260,9 @@ module JSON::LD
251
260
  # @param [String, #read, Hash, Array, JSON::LD::EvaluationContext] context
252
261
  # An optional external context to use additionally to the context embedded in input when expanding the input.
253
262
  # @param [Boolean] expanded (false) Input is already expanded
263
+ # @param [Proc] serializer (nil)
264
+ # A Serializer instance used for generating the JSON serialization of the result. If absent, the internal Ruby objects are returned, which can be transformed to JSON externally via `#to_json`.
265
+ # See {JSON::LD::API.serializer}.
254
266
  # @param [Hash{Symbol => Object}] options
255
267
  # @option options (see #initialize)
256
268
  # @option options [Boolean] :createAnnotations
@@ -262,7 +274,7 @@ module JSON::LD
262
274
  # @return [Object, Hash]
263
275
  # If a block is given, the result of evaluating the block is returned, otherwise, the flattened JSON-LD document
264
276
  # @see https://www.w3.org/TR/json-ld11-api/#framing-algorithm
265
- def self.flatten(input, context, expanded: false, **options)
277
+ def self.flatten(input, context, expanded: false, serializer: nil, **options)
266
278
  flattened = []
267
279
  options = {
268
280
  compactToRelative: true,
@@ -318,6 +330,7 @@ module JSON::LD
318
330
  end
319
331
  end
320
332
 
333
+ flattened = serializer.call(flattened, **options) if serializer
321
334
  block_given? ? yield(flattened) : flattened
322
335
  end
323
336
 
@@ -350,7 +363,7 @@ module JSON::LD
350
363
  # If a block is given, the result of evaluating the block is returned, otherwise, the framed JSON-LD document
351
364
  # @raise [InvalidFrame]
352
365
  # @see https://www.w3.org/TR/json-ld11-api/#framing-algorithm
353
- def self.frame(input, frame, expanded: false, **options)
366
+ def self.frame(input, frame, expanded: false, serializer: nil, **options)
354
367
  result = nil
355
368
  options = {
356
369
  base: (RDF::URI(input) if input.is_a?(String)),
@@ -379,7 +392,8 @@ module JSON::LD
379
392
  requestProfile: 'http://www.w3.org/ns/json-ld#frame',
380
393
  **options)
381
394
  if remote_doc.document.is_a?(String)
382
- MultiJson.load(remote_doc.document)
395
+ mj_opts = options.keep_if {|k,v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v)}
396
+ MultiJson.load(remote_doc.document, **mj_opts)
383
397
  else
384
398
  remote_doc.document
385
399
  end
@@ -467,6 +481,7 @@ module JSON::LD
467
481
  result
468
482
  end
469
483
 
484
+ result = serializer.call(result, **options) if serializer
470
485
  block_given? ? yield(result) : result
471
486
  end
472
487
 
@@ -528,18 +543,21 @@ module JSON::LD
528
543
  # The resulting `Array` is either returned or yielded, if a block is given.
529
544
  #
530
545
  # @param [RDF::Enumerable] input
546
+ # @param [Boolean] useRdfType (false)
547
+ # If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
548
+ # @param [Boolean] useNativeTypes (false) use native representations
549
+ # @param [Proc] serializer (nil)
550
+ # A Serializer instance used for generating the JSON serialization of the result. If absent, the internal Ruby objects are returned, which can be transformed to JSON externally via `#to_json`.
551
+ # See {JSON::LD::API.serializer}.
531
552
  # @param [Hash{Symbol => Object}] options
532
553
  # @option options (see #initialize)
533
- # @option options [Boolean] :useRdfType (false)
534
- # If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
535
- # @option options [Boolean] :useNativeTypes (false) use native representations
536
554
  # @yield jsonld
537
555
  # @yieldparam [Hash] jsonld
538
556
  # The JSON-LD document in expanded form
539
557
  # @yieldreturn [Object] returned object
540
558
  # @return [Object, Hash]
541
559
  # If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
542
- def self.fromRdf(input, useRdfType: false, useNativeTypes: false, **options, &block)
560
+ def self.fromRdf(input, useRdfType: false, useNativeTypes: false, serializer: nil, **options, &block)
543
561
  result = nil
544
562
 
545
563
  API.new(nil, nil, **options) do
@@ -548,6 +566,7 @@ module JSON::LD
548
566
  useNativeTypes: useNativeTypes)
549
567
  end
550
568
 
569
+ result = serializer.call(result, **options) if serializer
551
570
  block_given? ? yield(result) : result
552
571
  end
553
572
 
@@ -648,7 +667,8 @@ module JSON::LD
648
667
  end
649
668
  else
650
669
  validate_input(remote_doc.document, url: remote_doc.documentUrl) if validate
651
- MultiJson.load(remote_doc.document, **options)
670
+ mj_opts = options.keep_if {|k,v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v)}
671
+ MultiJson.load(remote_doc.document, **mj_opts)
652
672
  end
653
673
  end
654
674
 
@@ -682,8 +702,8 @@ module JSON::LD
682
702
  base_uri ||= url.base_uri if url.respond_to?(:base_uri)
683
703
  content_type = options[:content_type]
684
704
  content_type ||= url.content_type if url.respond_to?(:content_type)
685
- context_url = if url.respond_to?(:links) && url.links
686
- (content_type == 'appliaction/json' || content_type.match?(%r(application/(^ld)+json)))
705
+ context_url = if url.respond_to?(:links) && url.links &&
706
+ (content_type == 'application/json' || content_type.match?(%r(application/(^ld)+json)))
687
707
  link = url.links.find_link(LINK_REL_CONTEXT)
688
708
  link.href if link
689
709
  end
@@ -759,7 +779,8 @@ module JSON::LD
759
779
  raise JSON::LD::JsonLdError::LoadingDocumentFailed, "Script tag has type=#{element.attributes['type']}" unless element.attributes['type'].to_s.start_with?('application/ld+json')
760
780
  content = element.inner_html
761
781
  validate_input(content, url: url) if options[:validate]
762
- MultiJson.load(content, **options)
782
+ mj_opts = options.keep_if {|k,v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v)}
783
+ MultiJson.load(content, **mj_opts)
763
784
  elsif extractAllScripts
764
785
  res = []
765
786
  elements = if profile
@@ -773,7 +794,8 @@ module JSON::LD
773
794
  elements.each do |element|
774
795
  content = element.inner_html
775
796
  validate_input(content, url: url) if options[:validate]
776
- r = MultiJson.load(content, **options)
797
+ mj_opts = options.keep_if {|k,v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v)}
798
+ r = MultiJson.load(content, **mj_opts)
777
799
  if r.is_a?(Hash)
778
800
  res << r
779
801
  elsif r.is_a?(Array)
@@ -788,12 +810,27 @@ module JSON::LD
788
810
  raise JSON::LD::JsonLdError::LoadingDocumentFailed, "No script tag found" unless element
789
811
  content = element.inner_html
790
812
  validate_input(content, url: url) if options[:validate]
791
- MultiJson.load(content, **options)
813
+ mj_opts = options.keep_if {|k,v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v)}
814
+ MultiJson.load(content, **mj_opts)
792
815
  end
793
816
  rescue MultiJson::ParseError => e
794
817
  raise JSON::LD::JsonLdError::InvalidScriptElement, e.message
795
818
  end
796
819
 
820
+ ##
821
+ # The default serializer for serialzing Ruby Objects to JSON.
822
+ #
823
+ # Defaults to `MultiJson.dump`
824
+ #
825
+ # @param [Object] object
826
+ # @param [Array<Object>] args
827
+ # other arguments that may be passed for some specific implementation.
828
+ # @param [Hash<Symbol, Object>] options
829
+ # options passed from the invoking context.
830
+ def self.serializer(object, *args, **options)
831
+ MultiJson.dump(object, JSON_STATE)
832
+ end
833
+
797
834
  ##
798
835
  # Validate JSON using JsonLint, if loaded
799
836
  private
@@ -57,7 +57,7 @@ module JSON::LD
57
57
  end
58
58
 
59
59
  ##
60
- # Initializes the RDF/JSON reader instance.
60
+ # Initializes the JSON-LD reader instance.
61
61
  #
62
62
  # @param [IO, File, String] input
63
63
  # @param [Hash{Symbol => Object}] options
@@ -26,7 +26,8 @@ module JSON::LD
26
26
  unique_bnodes, rename_bnodes = @options[:unique_bnodes], @options.fetch(:rename_bnodes, true)
27
27
  # FIXME: document loader doesn't stream
28
28
  @base = RDF::URI(@options[:base] || base_uri)
29
- value = MultiJson.load(@doc, **@options)
29
+ mj_opts = @options.keep_if {|k,v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v)}
30
+ value = MultiJson.load(@doc, mj_opts)
30
31
  context_ref = @options[:expandContext]
31
32
  #context_ref = @options.fetch(:expandContext, remote_doc.contextUrl)
32
33
  context = Context.parse(context_ref, **@options)
@@ -11,7 +11,7 @@ module JSON::LD
11
11
  ##
12
12
  # @param [Hash{String => Object}] item
13
13
  # @param [RDF::Resource] graph_name
14
- # @param [Boolean] emitted triples are quoted triples.
14
+ # @param [Boolean] quoted emitted triples are quoted triples.
15
15
  # @yield statement
16
16
  # @yieldparam [RDF::Statement] statement
17
17
  # @return RDF::Resource the subject of this item
@@ -186,10 +186,6 @@ module JSON::LD
186
186
  # @return [Boolean]
187
187
  # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
188
188
  def accept?(accept_params)
189
- # Profiles that aren't specific IANA relations represent the URL
190
- # of a context or frame that may be subject to black- or white-listing
191
- profile = accept_params[:profile].to_s.split(/\s+/)
192
-
193
189
  if block_given?
194
190
  yield(accept_params)
195
191
  else
@@ -229,6 +225,8 @@ module JSON::LD
229
225
  # frame to use when serializing.
230
226
  # @option options [Boolean] :unique_bnodes (false)
231
227
  # Use unique bnode identifiers, defaults to using the identifier which the node was originall initialized with (if any).
228
+ # @option options [Proc] serializer (JSON::LD::API.serializer)
229
+ # A Serializer method used for generating the JSON serialization of the result.
232
230
  # @option options [Boolean] :stream (false)
233
231
  # Do not attempt to optimize graph presentation, suitable for streaming large graphs.
234
232
  # @yield [writer] `self`
@@ -239,6 +237,7 @@ module JSON::LD
239
237
  def initialize(output = $stdout, **options, &block)
240
238
  options[:base_uri] ||= options[:base] if options.key?(:base)
241
239
  options[:base] ||= options[:base_uri] if options.key?(:base_uri)
240
+ @serializer = options.fetch(:serializer, JSON::LD::API.method(:serializer))
242
241
  super do
243
242
  @repo = RDF::Repository.new
244
243
 
@@ -300,7 +299,7 @@ module JSON::LD
300
299
  else
301
300
 
302
301
  log_debug("writer") { "serialize #{@repo.count} statements, #{@options.inspect}"}
303
- result = API.fromRdf(@repo, **@options)
302
+ result = API.fromRdf(@repo, **@options.merge(serializer: nil))
304
303
 
305
304
  # Some options may be indicated from accept parameters
306
305
  profile = @options.fetch(:accept_params, {}).fetch(:profile, "").split(' ')
@@ -322,20 +321,20 @@ module JSON::LD
322
321
 
323
322
  # Rename BNodes to uniquify them, if necessary
324
323
  if options[:unique_bnodes]
325
- result = API.flatten(result, context, **@options)
324
+ result = API.flatten(result, context, **@options.merge(serializer: nil))
326
325
  end
327
326
 
328
327
  if frame = @options[:frame]
329
328
  # Perform framing, if given a frame
330
329
  log_debug("writer") { "frame result"}
331
- result = API.frame(result, frame, **@options)
330
+ result = API.frame(result, frame, **@options.merge(serializer: nil))
332
331
  elsif context
333
332
  # Perform compaction, if we have a context
334
333
  log_debug("writer") { "compact result"}
335
- result = API.compact(result, context, **@options)
334
+ result = API.compact(result, context, **@options.merge(serializer: nil))
336
335
  end
337
336
 
338
- @output.write(result.to_json(JSON_STATE))
337
+ @output.write(@serializer.call(result, **@options))
339
338
  end
340
339
 
341
340
  super
data/lib/json/ld.rb CHANGED
@@ -46,6 +46,9 @@ module JSON
46
46
  # Default context when compacting without one being specified
47
47
  DEFAULT_CONTEXT = "http://schema.org"
48
48
 
49
+ # Acceptable MultiJson adapters
50
+ MUTLI_JSON_ADAPTERS = %i(oj json_gem json_pure ok_json yajl nsjsonseerialization)
51
+
49
52
  KEYWORDS = Set.new(%w(
50
53
  @annotation
51
54
  @base
data/spec/api_spec.rb CHANGED
@@ -48,30 +48,78 @@ describe JSON::LD::API do
48
48
  context "with MultiJson adapter #{adapter.inspect}" do
49
49
  Dir.glob(File.expand_path(File.join(File.dirname(__FILE__), 'test-files/*-input.*'))) do |filename|
50
50
  test = File.basename(filename).sub(/-input\..*$/, '')
51
- frame = filename.sub(/-input\..*$/, '-frame.json')
52
- framed = filename.sub(/-input\..*$/, '-framed.json')
53
- compacted = filename.sub(/-input\..*$/, '-compacted.json')
54
- context = filename.sub(/-input\..*$/, '-context.json')
55
- expanded = filename.sub(/-input\..*$/, '-expanded.json')
51
+ frame = filename.sub(/-input\..*$/, '-frame.jsonld')
52
+ framed = filename.sub(/-input\..*$/, '-framed.jsonld')
53
+ compacted = filename.sub(/-input\..*$/, '-compacted.jsonld')
54
+ context = filename.sub(/-input\..*$/, '-context.jsonld')
55
+ expanded = filename.sub(/-input\..*$/, '-expanded.jsonld')
56
56
  ttl = filename.sub(/-input\..*$/, '-rdf.ttl')
57
57
 
58
58
  context test, skip: ("Not supported in JRuby" if RUBY_ENGINE == "jruby" && %w(oj yajl).include?(adapter.to_s)) do
59
- it "expands" do
60
- options = {logger: logger, adapter: adapter}
61
- options[:expandContext] = File.open(context) if context
62
- jld = described_class.expand(File.open(filename), **options)
63
- expect(jld).to produce_jsonld(JSON.load(File.open(expanded)), logger)
64
- end if File.exist?(expanded)
59
+ around do |example|
60
+ @file = File.open(filename)
61
+ case filename
62
+ when /.jsonld$/
63
+ @file.define_singleton_method(:content_type) {'application/ld+json'}
64
+ end
65
+ if context
66
+ @ctx_io = File.open(context)
67
+ case context
68
+ when /.jsonld$/
69
+ @ctx_io.define_singleton_method(:content_type) {'application/ld+json'}
70
+ end
71
+ end
72
+ example.run
73
+ @file.close
74
+ @ctx_io.close if @ctx_io
75
+ end
76
+
77
+ if File.exist?(expanded)
78
+ it "expands" do
79
+ options = {logger: logger, adapter: adapter}
80
+ options[:expandContext] = @ctx_io if context
81
+ jld = described_class.expand(@file, **options)
82
+ expect(jld).to produce_jsonld(JSON.parse(File.read(expanded)), logger)
83
+ end
84
+
85
+ it "expands with serializer" do
86
+ options = {logger: logger, adapter: adapter}
87
+ options[:expandContext] = @ctx_io if context
88
+ jld = described_class.expand(@file, serializer: JSON::LD::API.method(:serializer), **options)
89
+ expect(jld).to be_a(String)
90
+ expect(JSON.load(jld)).to produce_jsonld(JSON.parse(File.read(expanded)), logger)
91
+ end
92
+ end
65
93
 
66
- it "compacts" do
67
- jld = described_class.compact(File.open(filename), File.open(context), adapter: adapter, logger: logger)
68
- expect(jld).to produce_jsonld(JSON.load(File.open(compacted)), logger)
69
- end if File.exist?(compacted) && File.exist?(context)
94
+ if File.exist?(compacted) && File.exist?(context)
95
+ it "compacts" do
96
+ jld = described_class.compact(@file, @ctx_io, adapter: adapter, logger: logger)
97
+ expect(jld).to produce_jsonld(JSON.parse(File.read(compacted)), logger)
98
+ end
99
+
100
+ it "compacts with serializer" do
101
+ jld = described_class.compact(@file, @ctx_io, serializer: JSON::LD::API.method(:serializer), adapter: adapter, logger: logger)
102
+ expect(jld).to be_a(String)
103
+ expect(JSON.load(jld)).to produce_jsonld(JSON.parse(File.read(compacted)), logger)
104
+ end
105
+ end
70
106
 
71
- it "frame" do
72
- jld = described_class.frame(File.open(filename), File.open(frame), adapter: adapter, logger: logger)
73
- expect(jld).to produce_jsonld(JSON.load(File.open(framed)), logger)
74
- end if File.exist?(framed) && File.exist?(frame)
107
+ if File.exist?(framed) && File.exist?(frame)
108
+ it "frames" do
109
+ File.open(frame) do |frame_io|
110
+ jld = described_class.frame(@file, frame_io, adapter: adapter, logger: logger)
111
+ expect(jld).to produce_jsonld(JSON.parse(File.read(framed)), logger)
112
+ end
113
+ end
114
+
115
+ it "frames with serializer" do
116
+ File.open(frame) do |frame_io|
117
+ jld = described_class.frame(@file, frame_io, serializer: JSON::LD::API.method(:serializer), adapter: adapter, logger: logger)
118
+ expect(jld).to be_a(String)
119
+ expect(JSON.load(jld)).to produce_jsonld(JSON.parse(File.read(framed)), logger)
120
+ end
121
+ end
122
+ end
75
123
 
76
124
  it "toRdf" do
77
125
  expect(RDF::Repository.load(filename, format: :jsonld, adapter: adapter, logger: logger)).to be_equivalent_graph(RDF::Repository.load(ttl), logger: logger)
data/spec/format_spec.rb CHANGED
@@ -73,8 +73,8 @@ describe JSON::LD::Format do
73
73
  describe ".cli_commands", skip: Gem.win_platform? do
74
74
  require 'rdf/cli'
75
75
  let(:ttl) {File.expand_path("../test-files/test-1-rdf.ttl", __FILE__)}
76
- let(:json) {File.expand_path("../test-files/test-1-input.json", __FILE__)}
77
- let(:context) {File.expand_path("../test-files/test-1-context.json", __FILE__)}
76
+ let(:json) {File.expand_path("../test-files/test-1-input.jsonld", __FILE__)}
77
+ let(:context) {File.expand_path("../test-files/test-1-context.jsonld", __FILE__)}
78
78
 
79
79
  describe "#expand" do
80
80
  it "expands RDF" do
data/spec/frame_spec.rb CHANGED
@@ -2438,7 +2438,31 @@ describe JSON::LD::API do
2438
2438
  "@id": "ex:entity1"
2439
2439
  }),
2440
2440
  processingMode: "json-ld-1.1"
2441
- }
2441
+ },
2442
+ "don't embed list elements": {
2443
+ frame: %({
2444
+ "@context": {"ex": "http://example.org/"},
2445
+ "ex:embed": {
2446
+ "@list": [{"@embed": "@never"}]
2447
+ }
2448
+ }),
2449
+ input: %({
2450
+ "@context": {"ex": "http://example.org/"},
2451
+ "@id": "ex:Sub1",
2452
+ "ex:embed": {
2453
+ "@list": [{
2454
+ "@id": "ex:Sub2",
2455
+ "ex:prop": "property"
2456
+ }]
2457
+ }
2458
+ }),
2459
+ output: %({
2460
+ "@context": {"ex": "http://example.org/"},
2461
+ "@id": "ex:Sub1",
2462
+ "ex:embed": {"@list": [{"@id": "ex:Sub2"}]}
2463
+ }),
2464
+ processingMode: "json-ld-1.1"
2465
+ },
2442
2466
  }.each do |title, params|
2443
2467
  it title do
2444
2468
  do_frame(params)
data/spec/suite_helper.rb CHANGED
@@ -60,6 +60,7 @@ module RDF::Util
60
60
  document_options[:headers][:content_type] = options[:contentType] if options[:contentType]
61
61
 
62
62
  remote_document = RDF::Util::File::RemoteDocument.new(response.read, **document_options)
63
+ response.close
63
64
  if block_given?
64
65
  return yield remote_document
65
66
  else
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-ld
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 3.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregg Kellogg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-11 00:00:00.000000000 Z
11
+ date: 2022-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdf
@@ -357,55 +357,52 @@ files:
357
357
  - spec/suite_remote_doc_spec.rb
358
358
  - spec/suite_to_rdf_spec.rb
359
359
  - spec/support/extensions.rb
360
- - spec/test-files/test-1-compacted.json
361
- - spec/test-files/test-1-context.json
362
- - spec/test-files/test-1-expanded.json
363
- - spec/test-files/test-1-input.json
364
- - spec/test-files/test-1-normalized.json
360
+ - spec/test-files/test-1-compacted.jsonld
361
+ - spec/test-files/test-1-context.jsonld
362
+ - spec/test-files/test-1-expanded.jsonld
363
+ - spec/test-files/test-1-input.jsonld
365
364
  - spec/test-files/test-1-rdf.ttl
366
- - spec/test-files/test-2-compacted.json
367
- - spec/test-files/test-2-context.json
368
- - spec/test-files/test-2-expanded.json
369
- - spec/test-files/test-2-input.json
370
- - spec/test-files/test-2-normalized.json
365
+ - spec/test-files/test-2-compacted.jsonld
366
+ - spec/test-files/test-2-context.jsonld
367
+ - spec/test-files/test-2-expanded.jsonld
368
+ - spec/test-files/test-2-input.jsonld
371
369
  - spec/test-files/test-2-rdf.ttl
372
- - spec/test-files/test-3-compacted.json
373
- - spec/test-files/test-3-context.json
374
- - spec/test-files/test-3-expanded.json
375
- - spec/test-files/test-3-input.json
376
- - spec/test-files/test-3-normalized.json
370
+ - spec/test-files/test-3-compacted.jsonld
371
+ - spec/test-files/test-3-context.jsonld
372
+ - spec/test-files/test-3-expanded.jsonld
373
+ - spec/test-files/test-3-input.jsonld
377
374
  - spec/test-files/test-3-rdf.ttl
378
- - spec/test-files/test-4-compacted.json
379
- - spec/test-files/test-4-context.json
380
- - spec/test-files/test-4-expanded.json
381
- - spec/test-files/test-4-input.json
375
+ - spec/test-files/test-4-compacted.jsonld
376
+ - spec/test-files/test-4-context.jsonld
377
+ - spec/test-files/test-4-expanded.jsonld
378
+ - spec/test-files/test-4-input.jsonld
382
379
  - spec/test-files/test-4-rdf.ttl
383
- - spec/test-files/test-5-compacted.json
384
- - spec/test-files/test-5-context.json
385
- - spec/test-files/test-5-expanded.json
386
- - spec/test-files/test-5-input.json
380
+ - spec/test-files/test-5-compacted.jsonld
381
+ - spec/test-files/test-5-context.jsonld
382
+ - spec/test-files/test-5-expanded.jsonld
383
+ - spec/test-files/test-5-input.jsonld
387
384
  - spec/test-files/test-5-rdf.ttl
388
- - spec/test-files/test-6-compacted.json
389
- - spec/test-files/test-6-context.json
390
- - spec/test-files/test-6-expanded.json
391
- - spec/test-files/test-6-input.json
385
+ - spec/test-files/test-6-compacted.jsonld
386
+ - spec/test-files/test-6-context.jsonld
387
+ - spec/test-files/test-6-expanded.jsonld
388
+ - spec/test-files/test-6-input.jsonld
392
389
  - spec/test-files/test-6-rdf.ttl
393
- - spec/test-files/test-7-compacted.json
394
- - spec/test-files/test-7-context.json
395
- - spec/test-files/test-7-expanded.json
396
- - spec/test-files/test-7-input.json
390
+ - spec/test-files/test-7-compacted.jsonld
391
+ - spec/test-files/test-7-context.jsonld
392
+ - spec/test-files/test-7-expanded.jsonld
393
+ - spec/test-files/test-7-input.jsonld
397
394
  - spec/test-files/test-7-rdf.ttl
398
- - spec/test-files/test-8-compacted.json
399
- - spec/test-files/test-8-context.json
400
- - spec/test-files/test-8-expanded.json
401
- - spec/test-files/test-8-frame.json
402
- - spec/test-files/test-8-framed.json
403
- - spec/test-files/test-8-input.json
395
+ - spec/test-files/test-8-compacted.jsonld
396
+ - spec/test-files/test-8-context.jsonld
397
+ - spec/test-files/test-8-expanded.jsonld
398
+ - spec/test-files/test-8-frame.jsonld
399
+ - spec/test-files/test-8-framed.jsonld
400
+ - spec/test-files/test-8-input.jsonld
404
401
  - spec/test-files/test-8-rdf.ttl
405
- - spec/test-files/test-9-compacted.json
406
- - spec/test-files/test-9-context.json
407
- - spec/test-files/test-9-expanded.json
408
- - spec/test-files/test-9-input.json
402
+ - spec/test-files/test-9-compacted.jsonld
403
+ - spec/test-files/test-9-context.jsonld
404
+ - spec/test-files/test-9-expanded.jsonld
405
+ - spec/test-files/test-9-input.jsonld
409
406
  - spec/to_rdf_spec.rb
410
407
  - spec/writer_spec.rb
411
408
  homepage: https://github.com/ruby-rdf/json-ld
@@ -466,52 +463,49 @@ test_files:
466
463
  - spec/support/extensions.rb
467
464
  - spec/to_rdf_spec.rb
468
465
  - spec/writer_spec.rb
469
- - spec/test-files/test-1-compacted.json
470
- - spec/test-files/test-1-context.json
471
- - spec/test-files/test-1-expanded.json
472
- - spec/test-files/test-1-input.json
473
- - spec/test-files/test-1-normalized.json
466
+ - spec/test-files/test-1-compacted.jsonld
467
+ - spec/test-files/test-1-context.jsonld
468
+ - spec/test-files/test-1-expanded.jsonld
469
+ - spec/test-files/test-1-input.jsonld
474
470
  - spec/test-files/test-1-rdf.ttl
475
- - spec/test-files/test-2-compacted.json
476
- - spec/test-files/test-2-context.json
477
- - spec/test-files/test-2-expanded.json
478
- - spec/test-files/test-2-input.json
479
- - spec/test-files/test-2-normalized.json
471
+ - spec/test-files/test-2-compacted.jsonld
472
+ - spec/test-files/test-2-context.jsonld
473
+ - spec/test-files/test-2-expanded.jsonld
474
+ - spec/test-files/test-2-input.jsonld
480
475
  - spec/test-files/test-2-rdf.ttl
481
- - spec/test-files/test-3-compacted.json
482
- - spec/test-files/test-3-context.json
483
- - spec/test-files/test-3-expanded.json
484
- - spec/test-files/test-3-input.json
485
- - spec/test-files/test-3-normalized.json
476
+ - spec/test-files/test-3-compacted.jsonld
477
+ - spec/test-files/test-3-context.jsonld
478
+ - spec/test-files/test-3-expanded.jsonld
479
+ - spec/test-files/test-3-input.jsonld
486
480
  - spec/test-files/test-3-rdf.ttl
487
- - spec/test-files/test-4-compacted.json
488
- - spec/test-files/test-4-context.json
489
- - spec/test-files/test-4-expanded.json
490
- - spec/test-files/test-4-input.json
481
+ - spec/test-files/test-4-compacted.jsonld
482
+ - spec/test-files/test-4-context.jsonld
483
+ - spec/test-files/test-4-expanded.jsonld
484
+ - spec/test-files/test-4-input.jsonld
491
485
  - spec/test-files/test-4-rdf.ttl
492
- - spec/test-files/test-5-compacted.json
493
- - spec/test-files/test-5-context.json
494
- - spec/test-files/test-5-expanded.json
495
- - spec/test-files/test-5-input.json
486
+ - spec/test-files/test-5-compacted.jsonld
487
+ - spec/test-files/test-5-context.jsonld
488
+ - spec/test-files/test-5-expanded.jsonld
489
+ - spec/test-files/test-5-input.jsonld
496
490
  - spec/test-files/test-5-rdf.ttl
497
- - spec/test-files/test-6-compacted.json
498
- - spec/test-files/test-6-context.json
499
- - spec/test-files/test-6-expanded.json
500
- - spec/test-files/test-6-input.json
491
+ - spec/test-files/test-6-compacted.jsonld
492
+ - spec/test-files/test-6-context.jsonld
493
+ - spec/test-files/test-6-expanded.jsonld
494
+ - spec/test-files/test-6-input.jsonld
501
495
  - spec/test-files/test-6-rdf.ttl
502
- - spec/test-files/test-7-compacted.json
503
- - spec/test-files/test-7-context.json
504
- - spec/test-files/test-7-expanded.json
505
- - spec/test-files/test-7-input.json
496
+ - spec/test-files/test-7-compacted.jsonld
497
+ - spec/test-files/test-7-context.jsonld
498
+ - spec/test-files/test-7-expanded.jsonld
499
+ - spec/test-files/test-7-input.jsonld
506
500
  - spec/test-files/test-7-rdf.ttl
507
- - spec/test-files/test-8-compacted.json
508
- - spec/test-files/test-8-context.json
509
- - spec/test-files/test-8-expanded.json
510
- - spec/test-files/test-8-frame.json
511
- - spec/test-files/test-8-framed.json
512
- - spec/test-files/test-8-input.json
501
+ - spec/test-files/test-8-compacted.jsonld
502
+ - spec/test-files/test-8-context.jsonld
503
+ - spec/test-files/test-8-expanded.jsonld
504
+ - spec/test-files/test-8-frame.jsonld
505
+ - spec/test-files/test-8-framed.jsonld
506
+ - spec/test-files/test-8-input.jsonld
513
507
  - spec/test-files/test-8-rdf.ttl
514
- - spec/test-files/test-9-compacted.json
515
- - spec/test-files/test-9-context.json
516
- - spec/test-files/test-9-expanded.json
517
- - spec/test-files/test-9-input.json
508
+ - spec/test-files/test-9-compacted.jsonld
509
+ - spec/test-files/test-9-context.jsonld
510
+ - spec/test-files/test-9-expanded.jsonld
511
+ - spec/test-files/test-9-input.jsonld
@@ -1,8 +0,0 @@
1
- [{
2
- "@id": {
3
- "@id": "_:c14n0"
4
- },
5
- "http://xmlns.com/foaf/0.1/avatar": "http://twitter.com/account/profile_image/manusporny",
6
- "http://xmlns.com/foaf/0.1/homepage": "http://manu.sporny.org/",
7
- "http://xmlns.com/foaf/0.1/name": "Manu Sporny"
8
- }]
@@ -1,32 +0,0 @@
1
- [{
2
- "@id": {
3
- "@id": "http://example.org/library"
4
- },
5
- "http://example.org/vocab#contains": {
6
- "@id": "http://example.org/library/the-republic"
7
- },
8
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": {
9
- "@id": "http://example.org/vocab#Library"
10
- }
11
- }, {
12
- "@id": {
13
- "@id": "http://example.org/library/the-republic"
14
- },
15
- "http://example.org/vocab#contains": {
16
- "@id": "http://example.org/library/the-republic#introduction"
17
- },
18
- "http://purl.org/dc/elements/1.1/creator": "Plato",
19
- "http://purl.org/dc/elements/1.1/title": "The Republic",
20
- "@type": {
21
- "@id": "http://example.org/vocab#Book"
22
- }
23
- }, {
24
- "@id": {
25
- "@id": "http://example.org/library/the-republic#introduction"
26
- },
27
- "http://purl.org/dc/elements/1.1/description": "An introductory chapter on The Republic.",
28
- "http://purl.org/dc/elements/1.1/title": "The Introduction",
29
- "@type": {
30
- "@id": "http://example.org/vocab#Chapter"
31
- }
32
- }]
@@ -1,13 +0,0 @@
1
- [{
2
- "@id": {
3
- "@id": "_:c14n0"
4
- },
5
- "http://xmlns.com/foaf/0.1/age": {
6
- "@type": "http://www.w3.org/2001/XMLSchema#integer",
7
- "@value": "41"
8
- },
9
- "http://xmlns.com/foaf/0.1/homepage": {
10
- "@id": "http://manu.sporny.org/"
11
- },
12
- "http://xmlns.com/foaf/0.1/name": "Manu Sporny"
13
- }]