json-ld 2.0.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
1
3
  require 'rdf/nquads'
2
4
 
3
5
  module JSON::LD
@@ -9,8 +11,10 @@ module JSON::LD
9
11
  # Representation is in expanded form
10
12
  #
11
13
  # @param [Array<RDF::Statement>, RDF::Enumerable] input
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`.
12
16
  # @return [Array<Hash>] the JSON-LD document in normalized form
13
- def from_statements(input)
17
+ def from_statements(input, useRdfType: false)
14
18
  default_graph = {}
15
19
  graph_map = {'@default' => default_graph}
16
20
  node_usages_map = {}
@@ -22,7 +26,7 @@ module JSON::LD
22
26
 
23
27
  # For each triple in input
24
28
  input.each do |statement|
25
- log_debug("statement") { statement.to_nquads.chomp}
29
+ #log_debug("statement") { statement.to_nquads.chomp}
26
30
 
27
31
  name = statement.graph_name ? ec.expand_iri(statement.graph_name).to_s : '@default'
28
32
 
@@ -38,13 +42,13 @@ module JSON::LD
38
42
  statement.object.literal?
39
43
 
40
44
  # 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.
41
- if statement.predicate == RDF.type && statement.object.resource? && !@options[:useRdfType]
45
+ if statement.predicate == RDF.type && statement.object.resource? && !useRdfType
42
46
  merge_value(node, '@type', statement.object.to_s)
43
47
  next
44
48
  end
45
49
 
46
50
  # Set value to the result of using the RDF to Object Conversion algorithm, passing object and use native types.
47
- value = ec.expand_value(nil, statement.object, @options)
51
+ value = ec.expand_value(nil, statement.object, useNativeTypes: @options[:useNativeTypes], log_depth: @options[:log_depth])
48
52
 
49
53
  merge_value(node, statement.predicate.to_s, value)
50
54
 
@@ -71,7 +75,7 @@ module JSON::LD
71
75
  list, list_nodes = [], []
72
76
 
73
77
  # 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:
74
- log_debug("list element?") {node.to_json(JSON_STATE) rescue 'malformed json'}
78
+ #log_debug("list element?") {node.to_json(JSON_STATE) rescue 'malformed json'}
75
79
  while property == RDF.rest.to_s &&
76
80
  node_usages_map[node['@id']].uniq.length == 1 &&
77
81
  blank_node?(node) &&
@@ -118,7 +122,7 @@ module JSON::LD
118
122
  node.delete(:usages)
119
123
  result << node unless node_reference?(node)
120
124
  end
121
- log_debug("fromRdf") {result.to_json(JSON_STATE) rescue 'malformed json'}
125
+ #log_debug("fromRdf") {result.to_json(JSON_STATE) rescue 'malformed json'}
122
126
  result
123
127
  end
124
128
  end
@@ -1,3 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
1
3
  module JSON::LD
2
4
  ##
3
5
  # A JSON-LD parser in Ruby.
@@ -1,3 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
1
3
  module JSON::LD
2
4
  # Simple Ruby reflector class to provide native
3
5
  # access to JSON-LD objects
@@ -1,3 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
1
3
  module JSON::LD
2
4
  ##
3
5
  # Streaming writer interface.
@@ -17,7 +19,7 @@ module JSON::LD
17
19
  else Context.new.parse(@options[:context])
18
20
  end
19
21
 
20
- log_debug("prologue") {"context: #{context.inspect}"}
22
+ #log_debug("prologue") {"context: #{context.inspect}"}
21
23
  if context
22
24
  @output.puts %({"@context": #{context.serialize['@context'].to_json}, "@graph": [)
23
25
  else
@@ -37,7 +39,7 @@ module JSON::LD
37
39
  #
38
40
  # @return [void] `self`
39
41
  def stream_statement(statement)
40
- log_debug("ss") {"state: #{@state.inspect}, stmt: #{statement}"}
42
+ #log_debug("ss") {"state: #{@state.inspect}, stmt: #{statement}"}
41
43
  if @current_graph != statement.graph_name
42
44
  end_graph
43
45
  start_graph(statement.graph_name)
@@ -72,7 +74,7 @@ module JSON::LD
72
74
  # Complete open statements
73
75
  # @return [void] `self`
74
76
  def stream_epilogue
75
- log_debug("epilogue") {"state: #{@state.inspect}"}
77
+ #log_debug("epilogue") {"state: #{@state.inspect}"}
76
78
  end_graph
77
79
  if context
78
80
  @output.puts "\n]}"
@@ -85,7 +87,7 @@ module JSON::LD
85
87
  private
86
88
 
87
89
  def start_graph(resource)
88
- log_debug("start_graph") {"state: #{@state.inspect}, resource: #{resource}"}
90
+ #log_debug("start_graph") {"state: #{@state.inspect}, resource: #{resource}"}
89
91
  if resource
90
92
  @output.puts(",") if [:wrote_node, :wrote_graph].include?(@state)
91
93
  @output.puts %({"@id": "#{resource}", "@graph": [)
@@ -95,7 +97,7 @@ module JSON::LD
95
97
  end
96
98
 
97
99
  def end_graph
98
- log_debug("end_graph") {"state: #{@state.inspect}, ctx: #{@current_graph}"}
100
+ #log_debug("end_graph") {"state: #{@state.inspect}, ctx: #{@current_graph}"}
99
101
  end_node
100
102
  if @current_graph
101
103
  @output.write %(]})
@@ -104,7 +106,7 @@ module JSON::LD
104
106
  end
105
107
 
106
108
  def end_node
107
- log_debug("end_node") {"state: #{@state.inspect}, node: #{@current_node_def.to_json}"}
109
+ #log_debug("end_node") {"state: #{@state.inspect}, node: #{@current_node_def.to_json}"}
108
110
  @output.puts(",") if [:wrote_node, :wrote_graph].include?(@state)
109
111
  if @current_node_def
110
112
  node_def = if context
@@ -1,3 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
1
3
  require 'rdf'
2
4
  require 'rdf/nquads'
3
5
 
@@ -38,14 +40,14 @@ module JSON::LD
38
40
  end
39
41
 
40
42
  subject = item['@id'] ? as_resource(item['@id']) : node
41
- log_debug("item_to_rdf") {"subject: #{subject.to_ntriples rescue 'malformed rdf'}"}
43
+ #log_debug("item_to_rdf") {"subject: #{subject.to_ntriples rescue 'malformed rdf'}"}
42
44
  item.each do |property, values|
43
45
  case property
44
46
  when '@type'
45
47
  # If property is @type, construct triple as an RDF Triple composed of id, rdf:type, and object from values where id and object are represented either as IRIs or Blank Nodes
46
48
  values.each do |v|
47
49
  object = as_resource(v)
48
- log_debug("item_to_rdf") {"type: #{object.to_ntriples rescue 'malformed rdf'}"}
50
+ #log_debug("item_to_rdf") {"type: #{object.to_ntriples rescue 'malformed rdf'}"}
49
51
  yield RDF::Statement(subject, RDF.type, object, graph_name: graph_name)
50
52
  end
51
53
  when '@graph'
@@ -57,11 +59,11 @@ module JSON::LD
57
59
  raise "Huh?" unless values.is_a?(Hash)
58
60
  values.each do |prop, vv|
59
61
  predicate = as_resource(prop)
60
- log_debug("item_to_rdf") {"@reverse predicate: #{predicate.to_ntriples rescue 'malformed rdf'}"}
62
+ #log_debug("item_to_rdf") {"@reverse predicate: #{predicate.to_ntriples rescue 'malformed rdf'}"}
61
63
  # For each item in values
62
64
  vv.each do |v|
63
65
  if list?(v)
64
- log_debug("item_to_rdf") {"list: #{v.inspect}"}
66
+ #log_debug("item_to_rdf") {"list: #{v.inspect}"}
65
67
  # If item is a list object, initialize list_results as an empty array, and object to the result of the List Conversion algorithm, passing the value associated with the @list key from item and list_results.
66
68
  object = parse_list(v['@list'], graph_name: graph_name, &block)
67
69
 
@@ -70,7 +72,7 @@ module JSON::LD
70
72
  else
71
73
  # Otherwise, item is a value object or a node definition. Generate object as the result of the Object Converstion algorithm passing item.
72
74
  object = item_to_rdf(v, graph_name: graph_name, &block)
73
- log_debug("item_to_rdf") {"subject: #{object.to_ntriples rescue 'malformed rdf'}"}
75
+ #log_debug("item_to_rdf") {"subject: #{object.to_ntriples rescue 'malformed rdf'}"}
74
76
  # yield subject, prediate, and literal to results.
75
77
  yield RDF::Statement(object, predicate, subject, graph_name: graph_name)
76
78
  end
@@ -82,12 +84,12 @@ module JSON::LD
82
84
  # Otherwise, property is an IRI or Blank Node identifier
83
85
  # Initialize predicate from property as an IRI or Blank node
84
86
  predicate = as_resource(property)
85
- log_debug("item_to_rdf") {"predicate: #{predicate.to_ntriples rescue 'malformed rdf'}"}
87
+ #log_debug("item_to_rdf") {"predicate: #{predicate.to_ntriples rescue 'malformed rdf'}"}
86
88
 
87
89
  # For each item in values
88
90
  values.each do |v|
89
91
  if list?(v)
90
- log_debug("item_to_rdf") {"list: #{v.inspect}"}
92
+ #log_debug("item_to_rdf") {"list: #{v.inspect}"}
91
93
  # If item is a list object, initialize list_results as an empty array, and object to the result of the List Conversion algorithm, passing the value associated with the @list key from item and list_results.
92
94
  object = parse_list(v['@list'], graph_name: graph_name, &block)
93
95
 
@@ -96,7 +98,7 @@ module JSON::LD
96
98
  else
97
99
  # Otherwise, item is a value object or a node definition. Generate object as the result of the Object Converstion algorithm passing item.
98
100
  object = item_to_rdf(v, graph_name: graph_name, &block)
99
- log_debug("item_to_rdf") {"object: #{object.to_ntriples rescue 'malformed rdf'}"}
101
+ #log_debug("item_to_rdf") {"object: #{object.to_ntriples rescue 'malformed rdf'}"}
100
102
  # yield subject, prediate, and literal to results.
101
103
  yield RDF::Statement(subject, predicate, object, graph_name: graph_name)
102
104
  end
@@ -117,7 +119,7 @@ module JSON::LD
117
119
  # @return [Array<RDF::Statement>]
118
120
  # Statements for each item in the list
119
121
  def parse_list(list, graph_name: nil, &block)
120
- log_debug('parse_list') {"list: #{list.inspect}"}
122
+ #log_debug('parse_list') {"list: #{list.inspect}"}
121
123
 
122
124
  last = list.pop
123
125
  result = first_bnode = last ? node : RDF.nil
@@ -1,3 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
1
3
  module JSON::LD
2
4
  module Utils
3
5
  ##
@@ -1,3 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
1
3
  module JSON::LD::VERSION
2
4
  VERSION_FILE = File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "..", "VERSION")
3
5
  MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chomp.split(".")
@@ -1,3 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
1
3
  require 'json/ld/streaming_writer'
2
4
  module JSON::LD
3
5
  ##
@@ -92,6 +92,27 @@ describe JSON::LD::Context do
92
92
  expect(ec.provided_context).to produce(ctx, logger)
93
93
  end
94
94
  end
95
+
96
+ context "pre-loaded remote" do
97
+ let(:ctx) {"http://example.com/preloaded"}
98
+ before(:all) {
99
+ JSON::LD::Context.add_preloaded("http://example.com/preloaded",
100
+ JSON::LD::Context.new().parse({'foo' => "http://example.com/"})
101
+ )}
102
+ after(:all) {JSON::LD::Context::PRELOADED.clear}
103
+
104
+ it "does not load referenced context" do
105
+ expect(JSON::LD::API).not_to receive(:documentLoader).with(ctx, anything)
106
+ ec = subject.parse(ctx)
107
+ end
108
+
109
+ it "uses loaded context" do
110
+ ec = subject.parse(ctx)
111
+ expect(ec.send(:mappings)).to produce({
112
+ "foo" => "http://example.com/"
113
+ }, logger)
114
+ end
115
+ end
95
116
  end
96
117
 
97
118
  context "Array" do
@@ -356,6 +377,7 @@ describe JSON::LD::Context do
356
377
  "@language" => "en"
357
378
  }
358
379
  }, logger)
380
+ expect(subject.to_rb).not_to be_empty
359
381
  end
360
382
 
361
383
  it "@vocab" do
@@ -365,16 +387,18 @@ describe JSON::LD::Context do
365
387
  "@vocab" => "http://example.com/"
366
388
  }
367
389
  }, logger)
390
+ expect(subject.to_rb).not_to be_empty
368
391
  end
369
392
 
370
393
  it "term mappings" do
371
- expect(subject.
372
- parse({'foo' => "http://example.com/"}).send(:clear_provided_context).
373
- serialize).to produce({
394
+ c = subject.
395
+ parse({'foo' => "http://example.com/"}).send(:clear_provided_context)
396
+ expect(c.serialize).to produce({
374
397
  "@context" => {
375
398
  "foo" => "http://example.com/"
376
399
  }
377
400
  }, logger)
401
+ expect(c.to_rb).not_to be_empty
378
402
  end
379
403
 
380
404
  it "@type with dependent prefixes in a single context" do
@@ -1332,4 +1356,50 @@ describe JSON::LD::Context do
1332
1356
  expect(subject.reverse_term('reverse')).to eql subject.term_definitions['ex']
1333
1357
  end
1334
1358
  end
1359
+
1360
+ describe JSON::LD::Context::TermDefinition do
1361
+ context "with nothing" do
1362
+ subject {described_class.new("term")}
1363
+ its(:term) {is_expected.to eq "term"}
1364
+ its(:id) {is_expected.to be_nil}
1365
+ its(:to_rb) {is_expected.to eq %(TermDefinition.new("term"))}
1366
+ end
1367
+
1368
+ context "with id" do
1369
+ subject {described_class.new("term", id: "http://example.org/term")}
1370
+ its(:term) {is_expected.to eq "term"}
1371
+ its(:id) {is_expected.to eq "http://example.org/term"}
1372
+ its(:to_rb) {is_expected.to eq %(TermDefinition.new("term", id: "http://example.org/term"))}
1373
+ end
1374
+
1375
+ context "with type_mapping" do
1376
+ subject {described_class.new("term", type_mapping: "http://example.org/type")}
1377
+ its(:type_mapping) {is_expected.to eq "http://example.org/type"}
1378
+ its(:to_rb) {is_expected.to eq %(TermDefinition.new("term", type_mapping: "http://example.org/type"))}
1379
+ end
1380
+
1381
+ context "with container_mapping" do
1382
+ subject {described_class.new("term", container_mapping: "@set")}
1383
+ its(:container_mapping) {is_expected.to eq "@set"}
1384
+ its(:to_rb) {is_expected.to eq %(TermDefinition.new("term", container_mapping: "@set"))}
1385
+ end
1386
+
1387
+ context "with language_mapping" do
1388
+ subject {described_class.new("term", language_mapping: "en")}
1389
+ its(:language_mapping) {is_expected.to eq "en"}
1390
+ its(:to_rb) {is_expected.to eq %(TermDefinition.new("term", language_mapping: "en"))}
1391
+ end
1392
+
1393
+ context "with reverse_property" do
1394
+ subject {described_class.new("term", reverse_property: true)}
1395
+ its(:reverse_property) {is_expected.to be_truthy}
1396
+ its(:to_rb) {is_expected.to eq %(TermDefinition.new("term", reverse_property: true))}
1397
+ end
1398
+
1399
+ context "with simple" do
1400
+ subject {described_class.new("term", simple: true)}
1401
+ its(:simple) {is_expected.to be_truthy}
1402
+ its(:to_rb) {is_expected.to eq %(TermDefinition.new("term", simple: true))}
1403
+ end
1404
+ end
1335
1405
  end
@@ -512,7 +512,7 @@ describe JSON::LD::API do
512
512
  end
513
513
  end
514
514
 
515
- describe "@reverse", skip:true do
515
+ describe "@reverse" do
516
516
  {
517
517
  "embed matched frames with @reverse" => {
518
518
  frame: {
@@ -550,6 +550,44 @@ describe JSON::LD::API do
550
550
  }]
551
551
  }
552
552
  },
553
+ "embed matched frames with reversed property" => {
554
+ frame: {
555
+ "@context" => {
556
+ "ex" => "http://example.org/",
557
+ "excludes" => {"@reverse" => "ex:includes"}
558
+ },
559
+ "@type" => "ex:Type1",
560
+ "excludes" => {}
561
+ },
562
+ input: [
563
+ {
564
+ "@context" => {"ex" => "http://example.org/"},
565
+ "@id" => "ex:Sub1",
566
+ "@type" => "ex:Type1"
567
+ },
568
+ {
569
+ "@context" => {"ex" => "http://example.org/"},
570
+ "@id" => "ex:Sub2",
571
+ "@type" => "ex:Type2",
572
+ "ex:includes" => {"@id" => "ex:Sub1"}
573
+ },
574
+ ],
575
+ output:{
576
+ "@context" => {
577
+ "ex" => "http://example.org/",
578
+ "excludes" => {"@reverse" => "ex:includes"}
579
+ },
580
+ "@graph" => [{
581
+ "@id" => "ex:Sub1",
582
+ "@type" => "ex:Type1",
583
+ "excludes" => {
584
+ "@id" => "ex:Sub2",
585
+ "@type" => "ex:Type2",
586
+ "ex:includes" => {"@id" => "ex:Sub1"}
587
+ }
588
+ }]
589
+ }
590
+ },
553
591
  }.each do |title, params|
554
592
  it title do
555
593
  begin
@@ -583,5 +621,63 @@ describe JSON::LD::API do
583
621
  data = framed["@graph"].first
584
622
  expect(data["mising_value"]).to be_nil
585
623
  end
624
+
625
+ it "issue #28" do
626
+ input = JSON.parse %({
627
+ "@context": {
628
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#"
629
+ },
630
+ "@id": "http://www.myresource/uuid",
631
+ "http://www.myresource.com/ontology/1.0#talksAbout": [
632
+ {
633
+ "@id": "http://rdf.freebase.com/ns/m.018w8",
634
+ "rdfs:label": [
635
+ {
636
+ "@value": "Basketball",
637
+ "@language": "en"
638
+ }
639
+ ]
640
+ }
641
+ ]
642
+ })
643
+ frame = JSON.parse %({
644
+ "@context": {
645
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
646
+ "talksAbout": {
647
+ "@id": "http://www.myresource.com/ontology/1.0#talksAbout",
648
+ "@type": "@id"
649
+ },
650
+ "label": {
651
+ "@id": "rdfs:label",
652
+ "@language": "en"
653
+ }
654
+ },
655
+ "@id": "http://www.myresource/uuid"
656
+ })
657
+ expected = JSON.parse %({
658
+ "@context": {
659
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
660
+ "talksAbout": {
661
+ "@id": "http://www.myresource.com/ontology/1.0#talksAbout",
662
+ "@type": "@id"
663
+ },
664
+ "label": {
665
+ "@id": "rdfs:label",
666
+ "@language": "en"
667
+ }
668
+ },
669
+ "@graph": [
670
+ {
671
+ "@id": "http://www.myresource/uuid",
672
+ "talksAbout": {
673
+ "@id": "http://rdf.freebase.com/ns/m.018w8",
674
+ "label": "Basketball"
675
+ }
676
+ }
677
+ ]
678
+ })
679
+ framed = JSON::LD::API.frame(input, frame, logger: logger)
680
+ expect(framed).to produce(expected, logger)
681
+ end
586
682
  end
587
683
  end