From 1cc7c3fb06dd37d2a7e1e53b0fbe12e52249e473 Mon Sep 17 00:00:00 2001 From: Daan Broeder Date: Wed, 18 Feb 2026 17:07:18 +0100 Subject: [PATCH 1/4] Added many convienence and attribute filters: - cf.search.keyword - cf.search.org_name - relevant_organisations.name, relevant_organisations.indentifiers.scheme, relevant_organisations.indentifiers.value - srv_has_hosting_organisation.name, srv_has_hosting_organisation.scheme, srv_has_hosting_organisation.identifier - cf.search.org_name - pageQueryParam, pageSizeQueryParamoadded syntax examples for all these --- openapi/ver/current/skg-if-openapi.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/openapi/ver/current/skg-if-openapi.yaml b/openapi/ver/current/skg-if-openapi.yaml index fab69a9..db02265 100644 --- a/openapi/ver/current/skg-if-openapi.yaml +++ b/openapi/ver/current/skg-if-openapi.yaml @@ -2550,6 +2550,21 @@ components: description: search result page type enum: - search_result_page + page: + description: current page number + type: integer + examples: + - 1 + page_size: + description: maximum number of items per page + type: integer + examples: + - 10 + items_count: + description: number of items returned on this page + type: integer + examples: + - 10 prev_page: description: Previous page reference type: object From 2335052384e2b1abf3ca3d354645494aaba65aa1 Mon Sep 17 00:00:00 2001 From: Daan Broeder Date: Mon, 23 Feb 2026 14:01:44 +0100 Subject: [PATCH 2/4] Fix schema/doc inconsistency: allow identifier strings in cross-reference properties Several cross-reference properties (references to other entities) are documented as accepting plain identifier strings (e.g. "org_1", "ven1") but the schema defined them as $ref object types only, causing validators to reject data the docs explicitly show as valid. Changes from bare $ref / oneOf to anyOf: [string | $ref] for: - Product: topics[].term, relevant_organisations[], funding[], contributions[].declared_affiliations[], contributions[].by, manifestations[].biblio.in, manifestations[].biblio.hosting_data_source - Person/Agent: affiliations[].affiliation - Grant: beneficiaries[], contributions[].declared_affiliations[], contributions[].by, funding_agency API responses may still return expanded objects. --- openapi/ver/current/skg-if-openapi.yaml | 106 +++++++++++++++++++----- 1 file changed, 85 insertions(+), 21 deletions(-) diff --git a/openapi/ver/current/skg-if-openapi.yaml b/openapi/ver/current/skg-if-openapi.yaml index db02265..375dde8 100644 --- a/openapi/ver/current/skg-if-openapi.yaml +++ b/openapi/ver/current/skg-if-openapi.yaml @@ -1480,7 +1480,11 @@ components: required: [ "term" ] properties: term: - $ref: '#/components/schemas/Topic' + description: Identifier of a `topic`. May be a plain identifier string or a full Topic object. + anyOf: + - type: string + description: Topic identifier (local_identifier or external URI) + - $ref: '#/components/schemas/Topic' # TODO provenance ? contributions: type: array @@ -1494,14 +1498,27 @@ components: $ref: '#/components/schemas/ProductManifestation' relevant_organisations: type: array - description: List of relevant Organisation associated with the `product`, in case the individual affiliations of a `person` are not available. + description: > + List of relevant Organisation identifiers associated with the `product`, in case + the individual affiliations of a `person` are not available. Each item may be a + plain identifier string (local_identifier or external URI) or a full Organisation + object. API responses may expand identifiers to full Organisation objects. items: - $ref: '#/components/schemas/Organisation' + anyOf: + - type: string + description: Organisation identifier (local_identifier or external URI) + - $ref: '#/components/schemas/Organisation' funding: type: array - description: List of `grant` associated with the `product` + description: > + List of Grant identifiers associated with the `product`. Each item may be a + plain identifier string (local_identifier or external URI) or a full Grant + object. API responses may expand identifiers to full Grant objects. items: - $ref: '#/components/schemas/GrantLite' + anyOf: + - type: string + description: Grant identifier (local_identifier or external URI) + - $ref: '#/components/schemas/GrantLite' related_products: $ref: '#/components/schemas/ProductRelated' @@ -1581,8 +1598,12 @@ components: required: [ "by" ] properties: by: - description: The identifier of a `person` or `organisation` contributing to a `product`. - oneOf: + description: > + Identifier of a `person` or `organisation` contributing to a `product`. May be + a plain identifier string or a typed object (discriminated by entity_type). + anyOf: + - type: string + description: Agent identifier (local_identifier or external URI) - $ref: '#/components/schemas/PersonLite' - $ref: '#/components/schemas/Organisation' - $ref: '#/components/schemas/Agent' @@ -1593,10 +1614,16 @@ components: organisation: '#/components/schemas/Organisation' agent: '#/components/schemas/Agent' declared_affiliations: - description: List of `organisation` that reflect the declared affiliations of a `person` contributing to a `product`. + description: > + List of Organisation identifiers reflecting the declared affiliations of a `person` + contributing to a `product`. Each item may be a plain identifier string or a full + Organisation object. type: array items: - $ref: '#/components/schemas/Organisation' + anyOf: + - type: string + description: Organisation identifier (local_identifier or external URI) + - $ref: '#/components/schemas/Organisation' rank: type: integer x-faker: @@ -1819,9 +1846,21 @@ components: x-faker: fake : ['{{datatype.number(5)}}'] in: - $ref: '#/components/schemas/VenueLite' + description: > + Venue identifier for the manifestation. May be a plain identifier string + or a full Venue object. + anyOf: + - type: string + description: Venue identifier (local_identifier or external URI) + - $ref: '#/components/schemas/VenueLite' hosting_data_source : - $ref: '#/components/schemas/DataSourceLite' + description: > + Data source identifier for the manifestation. May be a plain identifier + string or a full Data Source object. + anyOf: + - type: string + description: Data source identifier (local_identifier or external URI) + - $ref: '#/components/schemas/DataSourceLite' ProductRelated: type: object description : A dictionary of objects representing related `product`, where the semantics of such relationships is specified as a key. @@ -2034,8 +2073,13 @@ components: required: [ "affiliation"] properties: affiliation: - description : "`organisation` a `person` is affiliated with" - $ref: "#/components/schemas/Organisation" + description: > + Organisation a `person` is affiliated with. May be a plain identifier + string or a full Organisation object. + anyOf: + - type: string + description: Organisation identifier (local_identifier or external URI) + - $ref: "#/components/schemas/Organisation" role : type: string default: "affiliate" @@ -2231,10 +2275,15 @@ components: examples: - "https://graspos.eu" beneficiaries: - description: "List of `organisation` funded by the `grant`" + description: > + List of Organisation identifiers funded by the `grant`. Each item may be a + plain identifier string or a full Organisation object. type: array items: - $ref: '#/components/schemas/Organisation' + anyOf: + - type: string + description: Organisation identifier (local_identifier or external URI) + - $ref: '#/components/schemas/Organisation' contributions: type: array description: List of objects describing a `person` or `organisation`, its role, contribution, rank, when working on the `grant`. @@ -2246,8 +2295,12 @@ components: description: 'Grant contribution. Describes a `person` or `organisation`, its role, contribution, rank, when working on a `grant`. See SKG-IF definition [Grant contribution](https://skg-if.github.io/interoperability-framework/docs/grant.html#contributions) ( entity_type:grant ).' properties: by: - description: The identifier of a `person` or `organisation` contributing to a `grant`. - oneOf: + description: > + Identifier of a `person` or `organisation` contributing to a `grant`. May be + a plain identifier string or a typed object (discriminated by entity_type). + anyOf: + - type: string + description: Agent identifier (local_identifier or external URI) - $ref: '#/components/schemas/PersonLite' - $ref: '#/components/schemas/Organisation' discriminator: @@ -2256,10 +2309,16 @@ components: person: '#/components/schemas/PersonLite' organisation: '#/components/schemas/Organisation' declared_affiliations: - description: List of `organisation` that reflect the declared affiliations of a `person` contributing to a `grant`. + description: > + List of Organisation identifiers reflecting the declared affiliations of a `person` + contributing to a `grant`. Each item may be a plain identifier string or a full + Organisation object. type: array items: - $ref: '#/components/schemas/Organisation' + anyOf: + - type: string + description: Organisation identifier (local_identifier or external URI) + - $ref: '#/components/schemas/Organisation' roles: description: | The roles that a `person` or `organisation` had in a `grant`.\ @@ -2350,8 +2409,13 @@ components: examples: - "GraspOS" funding_agency: - description : "`organisation` funding the `grant`." - $ref: "#/components/schemas/Organisation" + description: > + Organisation funding the `grant`. May be a plain identifier string + or a full Organisation object. + anyOf: + - type: string + description: Organisation identifier (local_identifier or external URI) + - $ref: "#/components/schemas/Organisation" funding_stream: description : "funding stream of the `grant`" type: string From 71e2bf4c086e5085c7a8f615162ffcea1c5acc0e Mon Sep 17 00:00:00 2001 From: Daan Broeder Date: Wed, 25 Feb 2026 09:53:54 +0100 Subject: [PATCH 3/4] =?UTF-8?q?support=20and=20document=20the=20use=20of?= =?UTF-8?q?=20different=20local=5Fidentifier=20formats=201.=20Full=20URL?= =?UTF-8?q?=20=E2=80=94=20any=20URL,=20used=20as-is=20as=20the=20entity=20?= =?UTF-8?q?identifier=20(e.g.=20a=20server=20API=20URL,=20a=20DOI,=20a=20R?= =?UTF-8?q?OR=20URL,=20or=20an=20SKG-IF=20sandbox=20URL)=202.=20Plain=20st?= =?UTF-8?q?ring=20=E2=80=94=20resolved=20by=20prepending=20the=20`@base`?= =?UTF-8?q?=20from=20the=20JSON-LD=20preamble;=20the=20framework=20prescri?= =?UTF-8?q?bes=20`https://w3id.org/skg-if/sandbox//`=20a?= =?UTF-8?q?s=20the=20`@base`=20for=20entities=20that=20have=20no=20indepen?= =?UTF-8?q?dently=20dereferenceable=20identifier=20of=20their=20own,=20pro?= =?UTF-8?q?ducing=20a=20*sandbox=20URL*=20=E2=80=94=20but=20any=20`@base`?= =?UTF-8?q?=20value=20is=20valid=203.=20On-the-fly=20=E2=80=94=20plain=20s?= =?UTF-8?q?tring=20using=20the=20template=20`otf=5F=5F=5F=5F?= =?UTF-8?q?=5F=5F`,=20also=20resolved=20via=20`@base`,?= =?UTF-8?q?=20for=20identifiers=20created=20on-the-fly=20during=20document?= =?UTF-8?q?=20generation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openapi/ver/current/skg-if-openapi.yaml | 29 ++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/openapi/ver/current/skg-if-openapi.yaml b/openapi/ver/current/skg-if-openapi.yaml index 375dde8..835999e 100644 --- a/openapi/ver/current/skg-if-openapi.yaml +++ b/openapi/ver/current/skg-if-openapi.yaml @@ -1380,12 +1380,35 @@ components: name: short_local_identifier in: path description: | - entity id. URL suffix used in OpenAPI get by id operations. \ - `https://[your-server-root-skg-if-url]/[products|persons|organisations|datasources|venues|topics]/{short_local_identifier}` \ - example `http://example.com/skg-if/api/products/c66c6-38be-4d5f-85db-d44c9` + The `local_identifier` of the entity to retrieve. Follows the SKG-IF convention — + always interpreted as a URL, in one of three forms: + + 1. **Full URL** — any URL, used as-is as the entity identifier (e.g. a server API URL, + a DOI, a ROR URL, or an SKG-IF sandbox URL) + 2. **Plain string** — resolved by prepending the `@base` from the JSON-LD preamble; + the framework prescribes `https://w3id.org/skg-if/sandbox//` as the + `@base` for entities that have no independently dereferenceable identifier of their own, + producing a *sandbox URL* — but any `@base` value is valid + 3. **On-the-fly** — plain string using the template `otf______`, + also resolved via `@base`, for identifiers created on-the-fly during document generation + + **Note:** identifiers containing `/` must have slashes percent-encoded as `%2F` in the URL. required: true schema: type: string + examples: + full_url_server: + summary: Full URL — server API URL as local_identifier + value: "http://example.com/skg-if/api/products/prd-c66c6-38be-4d5f-85db-d44c9f869333" + full_url_sandbox: + summary: Full URL — SKG-IF sandbox identifier (pre-expanded form of a plain string) + value: "https://w3id.org/skg-if/sandbox/clarin-vlo/11234/1-4816" + short_string: + summary: Plain string resolved via @base (slashes percent-encoded in URL as %2F) + value: "11234/1-4816" + on_the_fly: + summary: On-the-fly identifier resolved via @base + value: "otf___1730027051396___person-1" # filterQueryParam: # filterQueryParam duplicated in each search endpoint ( only way to add distinct examples for each endpoint ) # name: filter # in: query From 947c672a4edb43880094b68d500dc36e464d18e7 Mon Sep 17 00:00:00 2001 From: Daan Broeder Date: Mon, 9 Mar 2026 15:26:26 +0100 Subject: [PATCH 4/4] changes for "expand" flag expanding cross-referenced entities -added a number of new example files for testing the cross-entity referencing vs embedded (light) entities -modified app.py (FastAPI) to support full URL local_identifier handling, and handling expansion of cross-reffed entities when the expand=true fkag is set --- .../datasource_oxford_research_archive.json | 25 +++++++++ .../current/sample_data/grants/grant_1.json | 2 +- .../organisations/org_brown_university.json | 2 +- .../org_european_commission.json | 24 +++++++++ .../org_john_carter_brown_library.json | 29 ++++++++++ .../organisations/org_lab_of_science.json | 14 +++++ .../sample_data/persons/pers_john_doe.json | 14 +++++ .../persons/pers_josiah_carberry.json | 22 ++++++++ .../products/dataset_openaire_graph.json | 30 +++++++++++ .../products/journal_article_full.json | 2 +- .../products/product_expand_test.json | 53 +++++++++++++++++++ .../topics/topic_computer_science.json | 23 ++++++++ .../venue_journal_of_psychoceramics.json | 22 ++++++++ openapi/ver/current/skg-if-openapi.yaml | 40 ++++++++++++++ 14 files changed, 299 insertions(+), 3 deletions(-) create mode 100644 openapi/ver/current/sample_data/datasources/datasource_oxford_research_archive.json create mode 100644 openapi/ver/current/sample_data/organisations/org_european_commission.json create mode 100644 openapi/ver/current/sample_data/organisations/org_john_carter_brown_library.json create mode 100644 openapi/ver/current/sample_data/organisations/org_lab_of_science.json create mode 100644 openapi/ver/current/sample_data/persons/pers_john_doe.json create mode 100644 openapi/ver/current/sample_data/persons/pers_josiah_carberry.json create mode 100644 openapi/ver/current/sample_data/products/dataset_openaire_graph.json create mode 100644 openapi/ver/current/sample_data/products/product_expand_test.json create mode 100644 openapi/ver/current/sample_data/topics/topic_computer_science.json create mode 100644 openapi/ver/current/sample_data/venues/venue_journal_of_psychoceramics.json diff --git a/openapi/ver/current/sample_data/datasources/datasource_oxford_research_archive.json b/openapi/ver/current/sample_data/datasources/datasource_oxford_research_archive.json new file mode 100644 index 0000000..f304a4a --- /dev/null +++ b/openapi/ver/current/sample_data/datasources/datasource_oxford_research_archive.json @@ -0,0 +1,25 @@ +{ + "@context": [ + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", + {"@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + ], + "@graph": [ + { + "local_identifier": "http://example.com/skg-if/api/datasources/datasource_oxford_research_archive", + "entity_type": "datasource", + "identifiers": [ + { + "scheme": "doi", + "value": "10.25504/FAIRsharing.rkwr6y" + } + ], + "name": "Oxford University Research Archive", + "data_source_classification": "repository", + "research_product_types": [ + "research data", + "literature" + ] + } + ] +} diff --git a/openapi/ver/current/sample_data/grants/grant_1.json b/openapi/ver/current/sample_data/grants/grant_1.json index 73daf2a..7c34069 100644 --- a/openapi/ver/current/sample_data/grants/grant_1.json +++ b/openapi/ver/current/sample_data/grants/grant_1.json @@ -8,7 +8,7 @@ ], "@graph": [ { - "local_identifier": "http://example.com/skg-if/api/grants/6f368a3a-b1cf-498f-b2de-27135d1e0011", + "local_identifier": "http://example.com/skg-if/api/grants/grant_1", "identifiers": [ { "scheme": "doi", diff --git a/openapi/ver/current/sample_data/organisations/org_brown_university.json b/openapi/ver/current/sample_data/organisations/org_brown_university.json index d1bc04e..362b926 100644 --- a/openapi/ver/current/sample_data/organisations/org_brown_university.json +++ b/openapi/ver/current/sample_data/organisations/org_brown_university.json @@ -8,7 +8,7 @@ ], "@graph": [ { - "local_identifier": "http://example.com/skg-if/api/organisations/6f368a3a-b1cf-498f-b2de-222222222", + "local_identifier": "http://example.com/skg-if/api/organisations/org_brown_university", "entity_type": "organisation", "identifiers": [ { diff --git a/openapi/ver/current/sample_data/organisations/org_european_commission.json b/openapi/ver/current/sample_data/organisations/org_european_commission.json new file mode 100644 index 0000000..d049388 --- /dev/null +++ b/openapi/ver/current/sample_data/organisations/org_european_commission.json @@ -0,0 +1,24 @@ +{ + "@context": [ + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", + {"@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + ], + "@graph": [ + { + "local_identifier": "http://example.com/skg-if/api/organisations/org_european_commission", + "entity_type": "organisation", + "identifiers": [ + { + "scheme": "ror", + "value": "https://ror.org/00k4n6c32" + } + ], + "name": "European Commission", + "short_name": "EU", + "types": [ + "funder" + ] + } + ] +} diff --git a/openapi/ver/current/sample_data/organisations/org_john_carter_brown_library.json b/openapi/ver/current/sample_data/organisations/org_john_carter_brown_library.json new file mode 100644 index 0000000..0f6811c --- /dev/null +++ b/openapi/ver/current/sample_data/organisations/org_john_carter_brown_library.json @@ -0,0 +1,29 @@ +{ + "@context": [ + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", + {"@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + ], + "@graph": [ + { + "local_identifier": "http://example.com/skg-if/api/organisations/org_john_carter_brown_library", + "entity_type": "organisation", + "identifiers": [ + { + "scheme": "ror", + "value": "https://ror.org/05gq02987" + }, + { + "scheme": "ror", + "value": "https://ror.org/0274ane14" + } + ], + "name": "John Carter Brown Library, Brown University, Providence RI, US", + "short_name": "BU", + "country": "US", + "types": [ + "archive" + ] + } + ] +} diff --git a/openapi/ver/current/sample_data/organisations/org_lab_of_science.json b/openapi/ver/current/sample_data/organisations/org_lab_of_science.json new file mode 100644 index 0000000..e624c84 --- /dev/null +++ b/openapi/ver/current/sample_data/organisations/org_lab_of_science.json @@ -0,0 +1,14 @@ +{ + "@context": [ + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", + {"@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + ], + "@graph": [ + { + "local_identifier": "http://example.com/skg-if/api/organisations/org_lab_of_science", + "entity_type": "organisation", + "name": "Lab of science, unknown University, Antarctica" + } + ] +} diff --git a/openapi/ver/current/sample_data/persons/pers_john_doe.json b/openapi/ver/current/sample_data/persons/pers_john_doe.json new file mode 100644 index 0000000..96f6084 --- /dev/null +++ b/openapi/ver/current/sample_data/persons/pers_john_doe.json @@ -0,0 +1,14 @@ +{ + "@context": [ + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", + {"@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + ], + "@graph": [ + { + "local_identifier": "http://example.com/skg-if/api/persons/pers_john_doe", + "entity_type": "person", + "name": "John Doe" + } + ] +} diff --git a/openapi/ver/current/sample_data/persons/pers_josiah_carberry.json b/openapi/ver/current/sample_data/persons/pers_josiah_carberry.json new file mode 100644 index 0000000..b29db38 --- /dev/null +++ b/openapi/ver/current/sample_data/persons/pers_josiah_carberry.json @@ -0,0 +1,22 @@ +{ + "@context": [ + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", + {"@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + ], + "@graph": [ + { + "local_identifier": "http://example.com/skg-if/api/persons/pers_josiah_carberry", + "entity_type": "person", + "identifiers": [ + { + "scheme": "orcid", + "value": "0000-0002-1825-0097" + } + ], + "given_name": "Josiah", + "family_name": "Carberry", + "name": "Josiah Carberry" + } + ] +} diff --git a/openapi/ver/current/sample_data/products/dataset_openaire_graph.json b/openapi/ver/current/sample_data/products/dataset_openaire_graph.json new file mode 100644 index 0000000..e238009 --- /dev/null +++ b/openapi/ver/current/sample_data/products/dataset_openaire_graph.json @@ -0,0 +1,30 @@ +{ + "@context": [ + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", + {"@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + ], + "@graph": [ + { + "local_identifier": "http://example.com/skg-if/api/products/dataset_openaire_graph", + "entity_type": "product", + "product_type": "research data", + "titles": { + "en": ["OpenAIRE Graph dataset - new collected projects"] + }, + "abstracts": { + "en": ["The dataset includes metadata about projects grants collected by OpenAIRE since October 2024."] + }, + "identifiers": [ + { + "scheme": "doi", + "value": "10.5281/zenodo.14622592" + }, + { + "scheme": "openalex", + "value": "W4393781519" + } + ] + } + ] +} diff --git a/openapi/ver/current/sample_data/products/journal_article_full.json b/openapi/ver/current/sample_data/products/journal_article_full.json index c70f63f..b4089a3 100644 --- a/openapi/ver/current/sample_data/products/journal_article_full.json +++ b/openapi/ver/current/sample_data/products/journal_article_full.json @@ -8,7 +8,7 @@ ], "@graph": [ { - "local_identifier": "http://example.com/skg-if/api/products/614a6575-5d6c-416c-a8e1-ddd456d132", + "local_identifier": "http://example.com/skg-if/api/products/journal_article_full", "entity_type": "product", "product_type": "literature", "titles": { diff --git a/openapi/ver/current/sample_data/products/product_expand_test.json b/openapi/ver/current/sample_data/products/product_expand_test.json new file mode 100644 index 0000000..db6ad43 --- /dev/null +++ b/openapi/ver/current/sample_data/products/product_expand_test.json @@ -0,0 +1,53 @@ +{ + "@context": [ + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", + {"@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + ], + "@graph": [ + { + "local_identifier": "http://example.com/skg-if/api/products/product_expand_test", + "entity_type": "product", + "product_type": "literature", + "titles": { + "en": ["Expand flag test product — cross-references as plain identifier strings"] + }, + "abstracts": { + "en": ["This record is designed to test the expand=true flag. All cross-reference properties hold plain local_identifier strings. Most point to entities that exist as sample data files; one (the second relevant_organisation) points to a non-existent entity and will be marked UNEXPANDABLE."] + }, + "topics": [ + { + "term": "http://example.com/skg-if/api/topics/topic_computer_science" + } + ], + "relevant_organisations": [ + "http://example.com/skg-if/api/organisations/org_european_commission", + "http://example.com/skg-if/api/organisations/org_does_not_exist" + ], + "funding": [ + "http://example.com/skg-if/api/grants/grant_1" + ], + "contributions": [ + { + "role": "author", + "rank": 1, + "by": "http://example.com/skg-if/api/persons/pers_josiah_carberry", + "declared_affiliations": [ + "http://example.com/skg-if/api/organisations/org_brown_university" + ] + } + ], + "manifestations": [ + { + "biblio": { + "in": "http://example.com/skg-if/api/venues/venue_journal_of_psychoceramics", + "hosting_data_source": "http://example.com/skg-if/api/datasources/datasource_oxford_research_archive" + }, + "dates": { + "publication": ["2025-01-01"] + } + } + ] + } + ] +} diff --git a/openapi/ver/current/sample_data/topics/topic_computer_science.json b/openapi/ver/current/sample_data/topics/topic_computer_science.json new file mode 100644 index 0000000..01689eb --- /dev/null +++ b/openapi/ver/current/sample_data/topics/topic_computer_science.json @@ -0,0 +1,23 @@ +{ + "@context": [ + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", + {"@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + ], + "@graph": [ + { + "local_identifier": "http://example.com/skg-if/api/topics/topic_computer_science", + "entity_type": "topic", + "identifiers": [ + { + "scheme": "wikidata", + "value": "https://www.wikidata.org/wiki/Q21198" + } + ], + "labels": { + "en": "Computer Science", + "it": "Informatica" + } + } + ] +} diff --git a/openapi/ver/current/sample_data/venues/venue_journal_of_psychoceramics.json b/openapi/ver/current/sample_data/venues/venue_journal_of_psychoceramics.json new file mode 100644 index 0000000..19b775b --- /dev/null +++ b/openapi/ver/current/sample_data/venues/venue_journal_of_psychoceramics.json @@ -0,0 +1,22 @@ +{ + "@context": [ + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", + {"@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + ], + "@graph": [ + { + "local_identifier": "http://example.com/skg-if/api/venues/venue_journal_of_psychoceramics", + "entity_type": "venue", + "identifiers": [ + { + "scheme": "issn", + "value": "0264-3561" + } + ], + "name": "Journal of Psychoceramics", + "acronym": "JPC", + "type": "journal" + } + ] +} diff --git a/openapi/ver/current/skg-if-openapi.yaml b/openapi/ver/current/skg-if-openapi.yaml index 835999e..87e5d85 100644 --- a/openapi/ver/current/skg-if-openapi.yaml +++ b/openapi/ver/current/skg-if-openapi.yaml @@ -280,6 +280,7 @@ paths: summary : search product which title contains 'ocean' - $ref : '#/components/parameters/pageQueryParam' - $ref : '#/components/parameters/pageSizeQueryParam' + - $ref : '#/components/parameters/expandQueryParam' responses: '200': description: | @@ -494,6 +495,7 @@ paths: summary: Get all person with identifier scheme 'orcid' and id '0000-0002-1825-0097' - $ref : '#/components/parameters/pageQueryParam' - $ref : '#/components/parameters/pageSizeQueryParam' + - $ref : '#/components/parameters/expandQueryParam' responses: '200': description: Success @@ -717,6 +719,7 @@ paths: pattern: '^(,?.+:.+)*$' - $ref : '#/components/parameters/pageQueryParam' - $ref : '#/components/parameters/pageSizeQueryParam' + - $ref : '#/components/parameters/expandQueryParam' responses: '200': description: Success @@ -940,6 +943,7 @@ paths: summary: Get all grants with title containing `GraspOS` - $ref : '#/components/parameters/pageQueryParam' - $ref : '#/components/parameters/pageSizeQueryParam' + - $ref : '#/components/parameters/expandQueryParam' responses: '200': description: Success @@ -1066,6 +1070,7 @@ paths: summary: Get all venues with name containing 'Psychoceramics' - $ref : '#/components/parameters/pageQueryParam' - $ref : '#/components/parameters/pageSizeQueryParam' + - $ref : '#/components/parameters/expandQueryParam' responses: '200': description: Success @@ -1203,6 +1208,7 @@ paths: summary: Get all topics with label containing 'Solar' in the scheme 'myvocabulary' - $ref : '#/components/parameters/pageQueryParam' - $ref : '#/components/parameters/pageSizeQueryParam' + - $ref : '#/components/parameters/expandQueryParam' responses: '200': description: Success @@ -1331,6 +1337,7 @@ paths: summary: Get all datasources with name containing `Oxford` - $ref : '#/components/parameters/pageQueryParam' - $ref : '#/components/parameters/pageSizeQueryParam' + - $ref : '#/components/parameters/expandQueryParam' responses: '200': description: Success @@ -1432,6 +1439,39 @@ components: Search page size. limit search result size. schema: type: integer + expandQueryParam: + name: expand + in: query + description: | + When `true`, instruct the server to expand cross-reference properties from plain + `local_identifier` strings to inline entity objects wherever possible. + The schema for each property defines the expected representation — some properties + expand to Lite entities (e.g. `GrantLite` for `funding`, `VenueLite` for + `manifestations[].biblio.in`) while others expand to full entity objects + (e.g. `Organisation` for `relevant_organisations`). + + Applies to: `relevant_organisations`, `funding`, `contributions[].by`, + `contributions[].declared_affiliations`, `manifestations[].biblio.in`, + `manifestations[].biblio.hosting_data_source`, `topics[].term`, + `affiliations[].affiliation`, `beneficiaries`, and `funding_agency`. + + > **Background:** All cross-reference properties in the SKG-IF JSON-LD context + > (verified across all context versions, 0.1.0 onwards) are defined with + > `"@type": "@vocab"` — meaning they are IRI references (local_identifiers) at the + > ontology level. The inline Lite/entity object forms are an API-level convenience + > supported by the OpenAPI spec on top of the data model. Without `expand=true` + > (default), responses reflect whatever representation the data store holds. + > With `expand=true`, the server resolves string identifiers to entity objects + > where possible. + + If a referenced entity cannot be resolved, the server returns the original + identifier string suffixed by ` UNEXPANDABLE` to signal the failure. + + > **Note for implementers:** This parameter is optional. Servers that do not support + > expansion may ignore it or return HTTP 422. + schema: + type: boolean + default: false schemas: Product: type: object