# Extending JSON-LD AND Hydra Contexts ## JSON-LD

JSON-LD screencast
Watch the JSON-LD screencast

API Platform provides the possibility to extend the JSON-LD context of properties. This allows you to describe JSON-LD-typed values, inverse properties using the `@reverse` keyword, and you can even overwrite the `@id` property this way. Everything you define within the following annotation will be passed to the context. This provides a generic way to extend the context. ```php 'http://yourcustomid.com', '@type' => 'http://www.w3.org/2001/XMLSchema#string', 'someProperty' => [ 'a' => 'textA', 'b' => 'textB' ] ] )] public $name; // ... } ``` The generated context will now have your custom attributes set: `GET /contexts/Book` ```json { "@context": { "@vocab": "http://example.com/apidoc#", "hydra": "http://www.w3.org/ns/hydra/core#", "name": { "@id": "http://yourcustomid.com", "@type": "http://www.w3.org/2001/XMLSchema#string", "someProperty": { "a": "textA", "b": "textB" } } } } ``` Note that you do not have to provide the `@id` attribute. If you do not provide an `@id` attribute, the value from `iri` will be used. ### Extending the Context of a Whole Resource The `jsonldContext` option is also available on `#[ApiResource]` itself. Its main use is declaring namespace prefixes once for the whole resource, instead of repeating a full IRI on every property that needs one: ```php 'http://purl.org/dc/terms/'], )] class Book { // ... #[ApiProperty(types: ['https://schema.org/name'], iris: ['dct:title'])] public $name; // ... } ``` The `dct` prefix is merged into the top-level `@context`, so properties can then reference it through a compact IRI such as `dct:title`: `GET /contexts/Book` ```json { "@context": { "@vocab": "http://example.com/apidoc#", "hydra": "http://www.w3.org/ns/hydra/core#", "dct": "http://purl.org/dc/terms/", "name": "dct:title" } } ``` The resource-level context is merged into `@context` before the per-property entries are added, and each property's entry is then written to `@context[]`, overwriting anything already present at that key. In practice, the two never collide because the resource-level context is meant for prefix declarations, while a property's own entry is keyed by the property name; a collision only happens if a property is literally named after one of your prefixes, in which case the property wins. If an operation (for example a `Get` or a `Patch`) declares its own `jsonldContext`, that value is used as-is for that operation instead of the resource's: the two are not merged together, the operation's `jsonldContext` simply takes precedence. ## Hydra

Hydra screencast
Watch the Hydra screencast

It's also possible to replace the Hydra context used by the documentation generator: ```php 'bar']) ])] class Book { //... } ``` ```yaml # api/config/api_platform/resources.yaml # The YAML syntax is only supported for Symfony resources: App\ApiResource\Book: operations: ApiPlatform\Metadata\Get: hydraContext: { foo: "bar" } ``` ```xml bar ``` ### The `hydra:memberAssertion` Property For every resource exposing a collection operation, the generated Hydra API documentation (`GET /docs.jsonld`) automatically adds a `hydra:memberAssertion` entry to the entrypoint's `hydra:supportedProperty` for that collection. It asserts, as an `rdf:type` statement, that every member returned by the collection is an instance of the resource: ```json { "@id": "#Entrypoint/books", "@type": "hydra:Link", "domain": "#Entrypoint", "owl:maxCardinality": 1, "range": "hydra:Collection", "hydra:memberAssertion": { "hydra:property": { "@id": "rdf:type" }, "hydra:object": { "@id": "#Book" } }, "hydra:supportedOperation": ["..."] } ``` This assertion is generated automatically for every collection and isn't configurable through `jsonldContext` or `hydraContext`. > [!NOTE] Before API Platform 4.4, the same assertion was expressed as an `owl:equivalentClass` > restriction (an `owl:onProperty: hydra:member` / `owl:allValuesFrom: #Book` pair nested inside the > `range` array). `owl:equivalentClass` no longer appears anywhere in the generated Hydra > documentation: if you parse `range` and expect that structure, read `hydra:memberAssertion` > instead.