What is hoisting?
Hoisting is a technique used in API design to reorganize the structure of data in API requests and responses. Its main goal is to simplify the way data is presented by moving nested or deeply structured data to a higher level in the API’s response or request body. This process makes the data easier to work with for developers by reducing complexity and aligning the structure more closely with how resources are conceptually understood.
In essence, hoisting “flattens” data structures. For APIs, this means transforming responses or requests so that important information is more accessible and not buried within nested objects. This is particularly beneficial when dealing with APIs that serve complex data models, as it can make the data easier to parse and use without extensive traversal of nested objects.
When should you use hoisting?
Hoisting is usually applied in specific scenarios to improve the design and usability of APIs:
- Complex Nested Structures: Employ hoisting when your API deals with complex, deeply nested data. It streamlines access to important information, reducing the need for deep navigation.
- Frequent Data Access: Use hoisting for elements that are often accessed or critical to operations, making them more directly accessible.
- Data Model Alignment: Apply hoisting to better align the API’s data structure with the conceptual model of the resources.
Initial Structure: Without Hoisting
Initially, our data structure represents a hierarchical model with nested entities, depicted as a tree.
x-speakeasy-entity: 1
at the top, with entities 2 and 3 as direct descendants. Entity 2 further nests entities 4, which branches into 5 and 6.
Step 1: Selecting an entity for hoisting
Entity (2) is marked with x-speakeasy-entity
for hoisting.
Step 2
After applying hoisting, the structure is reorganized to prioritize x-speakeasy-entity: 2
, making its leaf nodes directly accessible and flattening the remaining structure.
x-speakeasy-entity: 2
(1)/ \2 3\4/ \5 6
Real-World Application: Flattening a “data” property
The JSON Schemas for Drink
, Drink
, and { drinkType: $DrinkType }
will be each considered the root of a Terraform Type Schema, and will be merged together to form the final Terraform Type Schema using Attribute Inference.
However, this is not always desired. Consider this alternative response:
Original
In the original API design, the request and response body are structured equivalently, without nested elements. This approach is straightforward but might not always suit complex data relationships or requirements.
Alternate
The alternate approach introduces a nested data
property in the API response, which can encapsulate the drink information more distinctly, albeit adding a layer of complexity in data access.
Original Code
Using the same request/response bodies, speakeasy would generate the following type schema
Alternative Code
When generated, the provider schema would look like this: not understanding that data
was a nested object, and instead treating it as a root of the schema.
The Fix: Implementing Hoisting
By applying the x-speakeasy-entity
annotation, we direct the schema generation process to consider the Drink
schema as the root of the type schema, effectively flattening the response structure for easier access.
Finalized Schema: Simplified Access
The final provider schema reflects a flattened structure, similar to the original API design but with the flexibility to include nested data when necessary.
/drinks:post:x-speakeasy-entity-operation: Drink#createparameters:- name: typein: querydescription: The type of drinkrequired: falsedeprecated: trueschema:$ref: "#/components/schemas/DrinkType"requestBody:required: truecontent:application/json:schema:$ref: "#/components/schemas/Drink"responses:"200":content:application/json:schema:$ref: "#/components/schemas/Drink""5XX":$ref: "#/components/responses/APIError"default:$ref: "#/components/responses/UnknownError"