Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions lib/pyld/jsonld.py
Original file line number Diff line number Diff line change
Expand Up @@ -1893,21 +1893,38 @@ def _compact(self, active_ctx, active_property, element, options):
)
if not index_key:
index_key = '@index'
container_key = self._compact_iri(
active_ctx, index_key, vocab=True
)
if index_key == '@index':
container_key = self._compact_iri(
active_ctx, index_key, vocab=True
)
key = expanded_item.get('@index')
if (
_is_object(compacted_item)
and container_key in compacted_item
):
del compacted_item[container_key]
else:
# Expand a term or compact IRI index mapping before re-compacting it.
expanded_index_key = self._expand_iri(
active_ctx, index_key, vocab=True
)
# Term selection for the index property can depend on its value.
index_value = JsonLdProcessor.arrayify(
expanded_item.get(expanded_index_key, [])
)
# Index maps use the first value as the map key.
index_value = index_value[0] if index_value else None
# Re-compact with the value so terms like predicate beat rdf:predicate.
container_key = self._compact_iri(
active_ctx,
expanded_index_key,
index_value,
vocab=True,
)
indexes = []
if _is_object(compacted_item):
indexes = JsonLdProcessor.arrayify(
compacted_item.get(index_key, [])
compacted_item.get(container_key, [])
)
if not indexes or not _is_string(indexes[0]):
key = None
Expand All @@ -1919,11 +1936,11 @@ def _compact(self, active_ctx, active_property, element, options):
and len(indexes) == 0
and _is_object(compacted_item)
):
del compacted_item[index_key]
del compacted_item[container_key]
elif len(indexes) == 1:
compacted_item[index_key] = indexes[0]
compacted_item[container_key] = indexes[0]
else:
compacted_item[index_key] = indexes
compacted_item[container_key] = indexes
elif '@id' in container:
id_key = self._compact_iri(
active_ctx, '@id', base=options.get('base', '')
Expand Down
2 changes: 0 additions & 2 deletions tests/runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -906,9 +906,7 @@ def write(self, filename):
'specVersion': ['json-ld-1.0'],
'idRegex': [
# uncategorized
'.*compact-manifest#t0112$',
'.*compact-manifest#tm023$',
'.*compact-manifest#t0113$',
'.*compact-manifest#tc028$',
],
},
Expand Down
90 changes: 90 additions & 0 deletions tests/test_jsonld.py
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,96 @@ def test_compact_same_length_uses_lexicographic_tiebreak(self):
assert "name" in result
assert "nick" not in result

def test_index_map_with_compact_iri_index_round_trips(self):
"""
When an @index container uses a compact IRI as its @index mapping,
compaction should use the indexed property value as the map key and
preserve the expanded representation on round-trip.
"""
context = {
"@context": {
"ex": "http://example.com/",
"items": {
"@id": "ex:items",
"@container": "@index",
"@index": "ex:rank",
},
}
}
expanded = [
{
"http://example.com/items": [
{
"http://example.com/rank": [{"@value": "first"}],
"http://example.com/name": [{"@value": "Alice"}],
}
]
}
]

compacted = jsonld.compact(expanded, context, {"skipExpansion": True})

assert compacted == {
"@context": context["@context"],
"items": {"first": {"ex:name": "Alice"}},
}
assert jsonld.expand(compacted) == expanded

def test_reverse_index_map_with_term_index_uses_property_value_as_key(self):
"""
When an @index container uses a term as its @index mapping, compaction
should still find the property key selected using the indexed value.
"""
context = {
"@context": {
"@version": 1.1,
"@base": "https://example.org/",
"@vocab": "https://example.net/ns#",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"statement": {
"@reverse": "rdf:subject",
"@container": "@index",
"@index": "predicate",
},
"predicate": {"@id": "rdf:predicate", "@type": "@vocab"},
"term": {"@id": "rdf:object", "@type": "@vocab"},
"addedIn": {"@type": "@id"},
}
}
expanded = [
{
"@id": "https://example.org/item/1",
"@reverse": {
"http://www.w3.org/1999/02/22-rdf-syntax-ns#subject": [
{
"https://example.net/ns#addedIn": [
{"@id": "https://example.org/v1"}
],
"http://www.w3.org/1999/02/22-rdf-syntax-ns#object": [
{"@id": "https://example.net/ns#A"}
],
"http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate": [
{
"@id": (
"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
"type"
)
}
],
}
]
},
}
]

compacted = jsonld.compact(expanded, context, {"skipExpansion": True})

assert compacted == {
"@context": context["@context"],
"@id": "item/1",
"statement": {"rdf:type": {"term": "A", "addedIn": "v1"}},
}

# Issue 91
def test_empty_context(self):
"""
Expand Down
Loading