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.
- checksums.yaml +4 -4
- data/README.md +12 -1
- data/VERSION +1 -1
- data/lib/json/ld.rb +3 -1
- data/lib/json/ld/api.rb +23 -20
- data/lib/json/ld/compact.rb +27 -26
- data/lib/json/ld/context.rb +499 -428
- data/lib/json/ld/expand.rb +284 -281
- data/lib/json/ld/extensions.rb +2 -0
- data/lib/json/ld/flatten.rb +84 -88
- data/lib/json/ld/format.rb +3 -1
- data/lib/json/ld/frame.rb +154 -163
- data/lib/json/ld/from_rdf.rb +10 -6
- data/lib/json/ld/reader.rb +2 -0
- data/lib/json/ld/resource.rb +2 -0
- data/lib/json/ld/streaming_writer.rb +8 -6
- data/lib/json/ld/to_rdf.rb +11 -9
- data/lib/json/ld/utils.rb +2 -0
- data/lib/json/ld/version.rb +2 -0
- data/lib/json/ld/writer.rb +2 -0
- data/spec/context_spec.rb +73 -3
- data/spec/frame_spec.rb +97 -1
- metadata +6 -7
data/lib/json/ld/from_rdf.rb
CHANGED
@@ -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? &&
|
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
|
data/lib/json/ld/reader.rb
CHANGED
data/lib/json/ld/resource.rb
CHANGED
@@ -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
|
data/lib/json/ld/to_rdf.rb
CHANGED
@@ -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
|
data/lib/json/ld/utils.rb
CHANGED
data/lib/json/ld/version.rb
CHANGED
data/lib/json/ld/writer.rb
CHANGED
data/spec/context_spec.rb
CHANGED
@@ -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
|
-
|
372
|
-
parse({'foo' => "http://example.com/"}).send(:clear_provided_context)
|
373
|
-
|
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
|
data/spec/frame_spec.rb
CHANGED
@@ -512,7 +512,7 @@ describe JSON::LD::API do
|
|
512
512
|
end
|
513
513
|
end
|
514
514
|
|
515
|
-
describe "@reverse"
|
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
|