Problem/Motivation
Today, schema for JSON API can only be generated by installing the https://www.drupal.org/project/schemata module, and even then, only imperfectly. Because the Symfony serialization component is not at all concerned with tracking data transformations which of course affect the schema: we don't expose 1:1 data as it is represented by Typed Data. And Typed Data is effectively Drupal's "data schema". JSON API uses it as a starting point, but then refines it.
Proposed resolution
Design and implement an improved normalization system with schema tracking built-in. To guarantee comprehensive schema support, and hence schemas you can actually rely on.
Remaining tasks
TBD
User interface changes
N/A
API changes
#2822768: [PP-1] Add information about the schema in the json:api resource will handle exposing this schema via JSON API.
Data model changes
TBD
Comments
Comment #2
e0ipso#3014277: ResourceTypes should know about their fields paves the path to field level schema.
Field level schema is the fundamental part of resource schemas. That is because the resource schema is a composition of field schemas using the JSON:API schema.
Comment #3
e0ipsoComment #4
wim leersFYI: we should look at https://api-platform.com/docs/schema-generator, since API Platform is also based on Symfony. There is probably at least something we can learn from them.
Comment #5
gabesulliceI quickly scanned that link @Wim Leers, it looks like that schema is generated from Symfony's "models" (akin to our entity types) and it makes no mention of serialization. I suspect it suffers from the same problems as using Typed Data to generate output schema.
@e0ipso asked me to record a couple challenges that we need to consider that came up in our weekly API-First meeting...
It seems the only way to properly generate output schema is to have normalizers for every data type in Drupal that can be determined without an instance of the data to be normalized. That means that they need to be determined by class name, maybe field metadata (like field settings or machine names) or within JSON:API by the
ResourceType(or a similar field-level value object).Unfortunately, what we've promised is that Drupal's normalization system will continue to work on the Typed Data level, IOW, we've "cordoned off" most of the normalization system, except for field properties. So, I'm not sure that normalizers can ever be deterministic at that level.
Another challenge in config entities, which don't have fields. The best we've got is Typed Data and/or config schema, but even then, we're SOL because there are instances of config schema with runtime dependencies, like in the following example from
block.schema.yml:As you can see, the type for
settingsdepends on the plugin ID in the block config.I think that it will be impossible in Drupal 8 to have 100% deterministic and static schema. IOW, we'll eventually have to accept that the output schema for some deep properties of a data structure might need to be
any. That said, I'm sure that there will be ways to get as close as possible to perfect schema for 99% of uses cases.Comment #6
gabesulliceComment #7
e0ipsoAgreed on the configuration entities.
Does this need to be true? Maybe we could put some useful constraints on that that work in our favor.
Comment #8
wim leersI agree with this.
As part of #2926507: Discourage @FieldType-level normalizers, encourage @DataType-level normalizers, to strengthen the API-First ecosystem, we could for example add a canonical: true key-value pair to the canonical
@DataTypenormalizers.But Gabe is absolutely right that today there is no way to guarantee this.
Comment #9
wim leersAfter having written #8, a thought crossed my mind: what if we'd add an additional method to
\Drupal\Core\TypedData\TypedDataInterfacein Drupal 9 or an optional interface in Drupal 8, for (de)normalization and schema purposes?That'd then represent the canonical (default) normalization for that type of data.
Comment #10
e0ipsoI had this relevant conversation the other day with @alexpott
Comment #11
wim leers#10: thanks for cross-posting that here! I saw that conversation in passing :) Great to have it on the permanent record here! 👍
Comment #12
wim leersComment #14
e0ipsoThere is a proof of concept to statically extract data definitions out of content entities and config entities.
In the situations described in #10 we can only say: well, there is a property with a data definition that varies from config entity to config entity, so we cannot know in advance. Hence the data definition is
undefined.https://git.drupalcode.org/project/jsonapi_schema/blob/8.x-1.x/src/Stati...
Comment #15
bradjones1Moving to core.