Skip to content

Commit ab4a4eb

Browse files
authored
Merge pull request #17 from AtomGraph/feat-top-level-json-ld
Recognise top-level JSON-LD in Operation.process_json
2 parents 7e79866 + 2b0d6f3 commit ab4a4eb

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "web-algebra"
3-
version = "1.2.0"
3+
version = "1.3.0"
44
description = "Composable RDF operations in JSON"
55
readme = "README.md"
66
license = "Apache-2.0"

src/web_algebra/operation.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from abc import ABC, abstractmethod
2+
import json
23
import logging
34
from typing import Type, Dict, Optional, Any, List, ClassVar, Union
45
from pydantic import BaseModel, Field, ConfigDict
@@ -9,6 +10,13 @@
910
from rdflib.query import Result
1011

1112

13+
# JSON-LD keyword set used to recognise a top-level dict as RDF data rather
14+
# than generic JSON to recurse into. Presence of any of these at the root is
15+
# a strong, unambiguous signal — they are JSON-LD reserved terms with no
16+
# legitimate meaning in non-RDF JSON.
17+
_JSONLD_KEYS = ("@context", "@graph", "@id", "@type")
18+
19+
1220
class Operation(ABC, BaseModel):
1321
"""
1422
Abstract base class for all operations with dual execution paths:
@@ -91,7 +99,24 @@ def process_json(
9199
# Return RDFLib objects as-is for operation chaining
92100
return result
93101

94-
# 🔁 Recurse into each value — allows nested @op inside JSON-LD and SPARQL bindings
102+
# JSON-LD shape recognition — a dict carrying any JSON-LD reserved
103+
# key is RDF data, not generic JSON to recurse into. Parse it
104+
# once at the runtime layer so every consuming op (POST, PUT,
105+
# Merge, ldh-Create*/Add*) receives an `rdflib.Graph` directly
106+
# instead of re-parsing identically inside its own
107+
# `execute_json`. Symmetric with the bare-value auto-wrap
108+
# below: that branch turns a JSON scalar into the matching
109+
# RDFLib term; this branch turns a JSON-LD object into the
110+
# matching RDFLib graph.
111+
if any(k in json_data for k in _JSONLD_KEYS):
112+
graph = Graph()
113+
graph.parse(data=json.dumps(json_data), format="json-ld")
114+
return graph
115+
116+
# 🔁 Recurse into each value — allows nested @op inside generic
117+
# JSON structures (e.g. SPARQL binding objects), without
118+
# collapsing pure-data dicts that JSON-LD detection above
119+
# already handled.
95120
return {
96121
k: cls.process_json(settings, v, context, variable_stack)
97122
for k, v in json_data.items()

0 commit comments

Comments
 (0)