Skip to content

Commit

Permalink
Finish 2.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
gkellogg committed Dec 13, 2017
2 parents e6f031a + 356b300 commit b4bb3c2
Show file tree
Hide file tree
Showing 31 changed files with 1,258 additions and 344 deletions.
80 changes: 80 additions & 0 deletions README.md
Expand Up @@ -298,6 +298,86 @@ The value of `@container` in a term definition can include `@id` or `@type`, in
}
}

### @graph containers and maps
A term can have `@container` set to include `@graph` optionally including `@id` or `@index` and `@set`. In the first form, with `@container` set to `@graph`, the value of a property is treated as a _simple graph object_, meaning that values treated as if they were contained in an object with `@graph`, creating _named graph_ with an anonymous name.

{
"@context": {
"@vocab": "http://example.org/",
"input": {"@container": "@graph"}
},
"input": {
"value": "x"
}
}

which expands to the following:

[{
"http://example.org/input": [{
"@graph": [{
"http://example.org/value": [{"@value": "x"}]
}]
}]
}]

Compaction reverses this process, optionally ensuring that a single value is contained within an array of `@container` also includes `@set`:

{
"@context": {
"@vocab": "http://example.org/",
"input": {"@container": ["@graph", "@set"]}
}
}

A graph map uses the map form already existing for `@index`, `@language`, `@type`, and `@id` where the index is either an index value or an id.

{
"@context": {
"@vocab": "http://example.org/",
"input": {"@container": ["@graph", "@index"]}
},
"input": {
"g1": {"value": "x"}
}
}

treats "g1" as an index, and expands to the following:

[{
"http://example.org/input": [{
"@index": "g1",
"@graph": [{
"http://example.org/value": [{"@value": "x"}]
}]
}]
}])

This can also include `@set` to ensure that, when compacting, a single value of an index will be in array form.

The _id_ version is similar:

{
"@context": {
"@vocab": "http://example.org/",
"input": {"@container": ["@graph", "@id"]}
},
"input": {
"http://example.com/g1": {"value": "x"}
}
}

which expands to:

[{
"http://example.org/input": [{
"@id": "http://example.com/g1",
"@graph": [{
"http://example.org/value": [{"@value": "x"}]
}]
}]
}])

### Transparent Nesting
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:

Expand Down
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
2.1.7
2.2.0
30 changes: 30 additions & 0 deletions example-files/implicit-named-graph-example.jsonld
@@ -0,0 +1,30 @@
{
"@context": {
"@version": 1.1,
"generatedAt": {
"@id": "http://www.w3.org/ns/prov#generatedAtTime",
"@type": "http://www.w3.org/2001/XMLSchema#date"
},
"Person": "http://xmlns.com/foaf/0.1/Person",
"name": "http://xmlns.com/foaf/0.1/name",
"knows": "http://xmlns.com/foaf/0.1/knows",
"claim": {
"@id": "https://w3id.org/credentials#claim",
"@container": "@graph"
}
},
"generatedAt": "2012-04-09",
"claim": [
{
"@id": "http://manu.sporny.org/about#manu",
"@type": "Person",
"name": "Manu Sporny",
"knows": "http://greggkellogg.net/foaf#me"
}, {
"@id": "http://greggkellogg.net/foaf#me",
"@type": "Person",
"name": "Gregg Kellogg",
"knows": "http://manu.sporny.org/about#manu"
}
]
}
28 changes: 18 additions & 10 deletions json-ld.gemspec
Expand Up @@ -26,19 +26,27 @@ Gem::Specification.new do |gem|

gem.required_ruby_version = '>= 2.2.2'
gem.requirements = []
gem.add_runtime_dependency 'rdf', '~> 2.2', '>= 2.2.8'
#gem.add_runtime_dependency 'rdf', '~> 3.0'
gem.add_runtime_dependency 'rdf', '>= 2.2.8', '< 4.0'
gem.add_runtime_dependency 'multi_json', '~> 1.12'
gem.add_development_dependency 'linkeddata', '~> 2.2'
#gem.add_development_dependency 'linkeddata', '~> 2.2'
gem.add_development_dependency 'linkeddata', '>= 2.2', '< 4.0'
gem.add_development_dependency 'jsonlint', '~> 0.2' unless RUBY_ENGINE == "jruby"
gem.add_development_dependency 'oj', '~> 2.17' unless RUBY_ENGINE == "jruby"
gem.add_development_dependency 'oj', '~> 2.18' unless RUBY_ENGINE == "jruby"
gem.add_development_dependency 'yajl-ruby', '~> 1.2' unless RUBY_ENGINE == "jruby"
gem.add_development_dependency 'rdf-isomorphic', '~> 2.0'
gem.add_development_dependency 'rdf-spec', '~> 2.2'
gem.add_development_dependency 'rdf-trig', '~> 2.0'
gem.add_development_dependency 'rdf-turtle', '~> 2.0'
gem.add_development_dependency 'rdf-vocab', '~> 2.0'
gem.add_development_dependency 'rdf-xsd', '~> 2.0'
gem.add_development_dependency 'rspec', '~> 3.5'
#gem.add_development_dependency 'rdf-isomorphic', '~> 3.0'
#gem.add_development_dependency 'rdf-spec', '~> 3.0'
#gem.add_development_dependency 'rdf-trig', '~> 3.0'
#gem.add_development_dependency 'rdf-turtle', '~> 3.0'
#gem.add_development_dependency 'rdf-vocab', '~> 3.0'
#gem.add_development_dependency 'rdf-xsd', '~> 3.0'
gem.add_development_dependency 'rdf-isomorphic', '>= 2.0', '< 4.0'
gem.add_development_dependency 'rdf-spec', '>= 2.2', '< 4.0'
gem.add_development_dependency 'rdf-trig', '>= 2.2', '< 4.0'
gem.add_development_dependency 'rdf-turtle', '>= 2.2', '< 4.0'
gem.add_development_dependency 'rdf-vocab', '>= 2.2', '< 4.0'
gem.add_development_dependency 'rdf-xsd', '>= 2.2', '< 4.0'
gem.add_development_dependency 'rspec', '~> 3.7'
gem.add_development_dependency 'rspec-its', '~> 1.2'
gem.add_development_dependency 'yard' , '~> 0.8'

Expand Down
66 changes: 56 additions & 10 deletions lib/json/ld/compact.rb
Expand Up @@ -82,6 +82,7 @@ def compact(element, property: nil)
if expanded_property == '@reverse'
compacted_value = compact(expanded_value, property: '@reverse')
#log_debug("@reverse") {"compacted_value: #{compacted_value.inspect}"}
# handle double-reversed properties
compacted_value.each do |prop, value|
if context.reverse?(prop)
value = [value] if !value.is_a?(Array) &&
Expand Down Expand Up @@ -112,7 +113,7 @@ def compact(element, property: nil)
next
end

if expanded_property == '@index' && context.container(property) == '@index'
if expanded_property == '@index' && context.container(property) == %w(@index)
#log_debug("@index") {"drop @index"}
next
end
Expand Down Expand Up @@ -162,13 +163,20 @@ def compact(element, property: nil)

container = context.container(item_active_property)
as_array = context.as_array?(item_active_property)
value = list?(expanded_item) ? expanded_item['@list'] : expanded_item

value = case
when list?(expanded_item) then expanded_item['@list']
when graph?(expanded_item) then expanded_item['@graph']
else expanded_item
end

compacted_item = compact(value, property: item_active_property)
#log_debug("") {" => compacted key: #{item_active_property.inspect} for #{compacted_item.inspect}"}

# handle @list
if list?(expanded_item)
compacted_item = [compacted_item] unless compacted_item.is_a?(Array)
unless container == '@list'
unless container == %w(@list)
al = context.compact_iri('@list', vocab: true, quiet: true)
compacted_item = {al => compacted_item}
if expanded_item.has_key?('@index')
Expand All @@ -178,25 +186,63 @@ def compact(element, property: nil)
else
raise JsonLdError::CompactionToListOfLists,
"key cannot have more than one list value" if nest_result.has_key?(item_active_property)
# Falls through to add list value below
end
end

if container == '@language' || container == '@index' || container == '@id' || container == '@type'
# Graph object compaction cases:
if graph?(expanded_item)
if container.include?('@graph') && container.include?('@id')
# container includes @graph and @id
map_object = nest_result[item_active_property] ||= {}
map_key = expanded_item['@id']
# If there is no @id, create a blank node identifier to use as an index
map_key = map_key ? context.compact_iri(map_key, quiet: true) : namer.get_name
merge_compacted_value(map_object, map_key, compacted_item)
elsif container.include?('@graph') && container.include?('@index') && simple_graph?(expanded_item)
# container includes @graph and @index and value is a simple graph object
map_object = nest_result[item_active_property] ||= {}
# If there is no @index, use @none
map_key = expanded_item['@index'] || '@none'
merge_compacted_value(map_object, map_key, compacted_item)
elsif container.include?('@graph') && simple_graph?(expanded_item)
# container includes @graph but not @id or @index and value is a simple graph object
# Drop through, where compacted_value will be added
compacted_item = [compacted_item] if
!compacted_item.is_a?(Array) && (!@options[:compactArrays] || as_array)
merge_compacted_value(nest_result, item_active_property, compacted_item)
else
# container does not include @graph or otherwise does not match one of the previous cases, redo compacted_item
compacted_item = [compacted_item]
al = context.compact_iri('@graph', vocab: true, quiet: true)
compacted_item = {al => compacted_item}
if expanded_item['@id']
al = context.compact_iri('@id', vocab: true, quiet: true)
compacted_item[al] = context.compact_iri(expanded_item['@id'], vocab: false, quiet: true).to_s
end
if expanded_item.has_key?('@index')
key = context.compact_iri('@index', vocab: true, quiet: true)
compacted_item[key] = expanded_item['@index']
end
compacted_item = [compacted_item] if !@options[:compactArrays] || as_array
merge_compacted_value(nest_result, item_active_property, compacted_item)
end
elsif !(container & %w(@language @index @id @type)).empty? && !container.include?('@graph')
map_object = nest_result[item_active_property] ||= {}
compacted_item = case container
when '@id'
when %w(@id)
id_prop = context.compact_iri('@id', vocab: true, quiet: true)
map_key = compacted_item[id_prop]
map_key = context.compact_iri(map_key, quiet: true)
compacted_item.delete(id_prop)
compacted_item
when '@index'
map_key = expanded_item[container]
when %w(@index)
map_key = expanded_item['@index']
compacted_item
when '@language'
map_key = expanded_item[container]
when %w(@language)
map_key = expanded_item['@language']
value?(expanded_item) ? expanded_item['@value'] : compacted_item
when '@type'
when %w(@type)
type_prop = context.compact_iri('@type', vocab: true, quiet: true)
map_key, *types = Array(compacted_item[type_prop])
map_key = context.compact_iri(map_key, vocab: true, quiet: true)
Expand Down

0 comments on commit b4bb3c2

Please sign in to comment.