Toolset to generate, validate, and handle JSON-LD
A lot of the work here is to work with JSON-LD: consume, parse, validate, normalize, denormalize. This meta issue is to work out approaches and tools. Work would be done in specific issues.
Notes:
Expansion, flattening
JSON-LD supports compacted and expanded formats as well as flattening of either. To avoid having to directly manage the inconsistencies of the compact format, we may want to standardize on expanded, https://w3c.github.io/json-ld-api/#expansion, and flattened. Flattening:
may drastically simplify the code required to process JSON-LD data in certain applications.
Then compact before returning. Discussion: More than JSON: ActivityPub and JSON-LD.
Validation
There's an unofficial ActivityPubSchema. Can we use that to validate against?
PHP implementations
General JSON-LD packages in PHP. Include support for expansion, compaction, etc.
- https://github.com/lanthaler/JsonLD
- https://github.com/digitalbazaar/php-json-ld
RDF
JSON-LD can be serialized to and from RDF; see https://w3c.github.io/json-ld-api/#rdf-serialization-deserialization.
Should we consider leveraging this to build on existing RDF support in Drupal?
Potentially relevant: JSON-LD Serializer for Drupal 8 and Islandora.
This module adds a simple Drupal entity to JSON-LD
normalizer/serializer/unserializerservice provider and a few supporting classes. It depends on RDF module and existing fields to RDF properties mappings to do its job.
Potentially relevant: JSON-LD Serializer for Drupal 8 and Islandora.
This module adds a simple Drupal entity to JSON-LD normalizer/serializer/unserializer service provider and a few supporting classes. It depends on RDF module and existing fields to RDF properties mappings to do its job.
Looking at the code of that, and the core hal+json module, rather focuses it for D8 in my mind ( - too long hacking around it for specifics in D7). I assume one way might well be taking the bit of extra code out of that module and use it. It looks pretty comprehensive (even if there's some additional stuff: routes, services for exceptions‽ etc. that are extra).
What it highlights as questions to me certainly do make me take a step back about rdf:
How difficult is it to make the default namespaces correct for the particular properties. So that code that doesn't actually parse JSON-LD but takes the JSON and the expected properties can read it; at the same time as those that do read namespaces do too. Complexity I can see making sure the output is right for consumers while in drupal it's a schema.org title, it's an dc terms title, and a activitypub title.
But at the same time there are equally consumers that are reading the namespaces, and/or read additional properties, so the output does want to include schema.org for example; and the output does need to keep track of which namespaces to add for consumers that care. So not doing so would be duplicating field mappings for rdf?
For consuming, would it make it easier respecting the namespaces or not? I'm guessing mapping to drupal entities would work fine without... but only up to a point of complexity? Is it possible to be relaxed about it (this would bypass the need to understand compact/extended I think?).
I've started on looking at https://github.com/Islandora/jsonld initial notes next. But to do so first I checked about modules for adding rdf properties to entities.
Generally they were focussed on schema.org and were more or less extensible. The other challenge was they all applied for adding to configurable fields and not base fields - or the entity bundle itself.
https://www.drupal.org/project/rdfui Was the most promising by description, but a bit broken. Code was very much to then add schema.org and only configurable fields.
https://www.drupal.org/project/json_ld_schema Implements https://github.com/spatie/schema-org for Drupal. Very comprehensive set of schema.org classes, but huge php code class based approach.
https://www.drupal.org/project/drupal2rdf Was incorrectly namespaced. It's semantic_map. It also provides a ui to apply rdf to fields (not base fields), but not as nice a (potential ui as rdfui). It is certainly highly extensible. For this it requires full rdf schema, but at least definition files and not php code and classes.
So in the end, for testing, I just made two node types and added some rdf with rdf_get_mapping
Ala:
$map = rdf_get_mapping('node', 'note');
$map->setBundleMapping([
'types' => ['sioc:Item', 'foaf:Document', 'activitystreams:Note'],
])
->setFieldMapping('title', [
'properties' => ['dc:title', 'activitystreams:name'],
])
->setFieldMapping('field_content', [
'properties' => ['activitystreams:content'],
])
->save();
And defined activitystreams name space in a hook_rdf_namespaces()
So https://github.com/Islandora/jsonld (also https://www.drupal.org/project/jsonld ) tested so far directly via the standard REST API node endpoint using ?_format=jsonld.
The endpoint doesn't by default implement @context the code is there and it will output for example:
{
"@context": {
"dc": "http://purl.org/dc/terms/",
"dc:title": {
"@type": "xsd:string"
},
"activitystreams": "https://www.w3.org/ns/activitystreams",
"activitystreams:name": {
"@type": "xsd:string"
},
"activitystreams:content": {
"@type": "xsd:string"
}
}
}
on http://example.com/jsonld/context/node/note
It doesn't by default output compacted property names, which are compulsory for activitystreams. Again it looks like the code to do so is in JsonldContextGenerator though.
It also outputs a @graph which is a must not for activitystreams. The graph is like json:api placing the referenced entities separately after the parent; activitystreams requires that there is just one entity - although it is normal to embed referenced entities properties inside (obvious example a Create activity entity with have the Note entity that was created with its properties in).
The module is good stuff though, and handles things I'd forgotten about - like language (which is mentioned in the actitystreams spec). It's contribution weekend, so I'll prod this a bit more later.
The way jsonld module handles the rdf looks like it could be successful. With a custom Normalizer - accepting particular namespaces / properties.
However, the way jsonapi module actually constructs the response, normalizing a JsonApiResource, looks much more hopeful for including (also normalized full versions of) referenced resources and updating the @context based on them.
The way jsonld module handles the rdf looks like it could be successful. With a custom Normalizer - accepting particular namespaces / properties.
However, the way jsonapi module actually constructs the response, normalizing a JsonApiResource, looks much more hopeful for including (also normalized full versions of) referenced resources and updating the @context based on them.
Another possibility besides the RDF module would be to build off the Schema.org Metatag module. Rely on it for the entity and field mappings, then translate Schema.org to Activity Streams.