Kitsu Core JSON:API (De)serializer
kitsu-core is a compact and framework-agnostic JavaScript/TypeScript library designed for the (de)serialization of JSON:API 1.0 compliant data structures. Currently in its 11.x stable release cycle, with version 11.1.1 being the latest, the project demonstrates an active development and release cadence, often publishing minor and patch updates within weeks or months. Its core differentiators include strict adherence to the JSON:API specification, automatic linking of relationships, and a zero-dependency footprint, making it highly tree-shakeable and suitable for both Node.js and browser environments. Recent updates have focused on significant performance improvements for large datasets (up to 1,000 times faster deserialization in v11.0.2) and introducing opt-in data hoisting features, allowing for more flexible data structuring post-deserialization. The library emphasizes minimal bundle size and broad modern environment compatibility.
Common errors
-
ReferenceError: require is not defined
cause Attempting to use CommonJS `require()` syntax in an ES Module (ESM) context (e.g., in a file with `.mjs` extension or when `"type": "module"` is set in `package.json`).fixChange `const { symbol } = require('kitsu-core');` to `import { symbol } from 'kitsu-core';`. Ensure your project's module configuration in `package.json` and `tsconfig.json` (if applicable) aligns with your chosen module system. -
TS2307: Cannot find module 'kitsu-core' or its corresponding type declarations.
cause TypeScript compiler cannot locate the type definitions for `kitsu-core`, or there's a mismatch in module resolution settings between `tsconfig.json` and the installed package version. This can be exacerbated by changes in v10.1.4 regarding fine-grained type exports.fixEnsure `kitsu-core` is correctly installed. Verify `tsconfig.json` includes `"compilerOptions": { "moduleResolution": "Node16", "module": "Node16", "allowSyntheticDefaultImports": true }` or `"Bundler"` for modern setups. Consider updating TypeScript and `kitsu-core` to their latest versions. -
Deserialized data does not have expected relationships linked, or relationships are present but not resolved to full objects.
cause The input JSON:API response is malformed, missing required `included` data, or does not strictly adhere to the JSON:API 1.0 specification for relationships and compound documents.fixCarefully inspect your JSON:API response to ensure it includes all related resources in the `included` array and that `relationships.data` objects correctly reference these resources by `type` and `id`.
Warnings
- breaking Upgrading to v11.x introduces potential breaking changes. The project's migration guide (linked in the README) details API changes, particularly around `deserialise` and `serialise` functions, and updates to internal type definitions and usage patterns. While the provided changelog for v11.0.0 mostly notes JSDoc fixes, major version bumps often imply broader compatibility or API shifts.
- gotcha This library is designed for modern Node.js environments (v18, 20, 22+) and browsers supporting ES Modules. While CommonJS `require` syntax is shown in some examples, the library is optimized for and increasingly leverages ES Modules. Mixing CJS and ESM in complex projects or using older Node.js versions (below 18) may lead to module resolution issues or require additional configuration.
- gotcha Version 11.1.0 introduced an opt-in data hoisting feature when deserializing responses. By default, JSON:API relationships are linked but maintain the specified structure. If you expect a flatter data structure where relationships are directly merged onto the parent object, you must explicitly enable and configure the `hoist` option in `deserialise`.
Install
-
npm install kitsu-core -
yarn add kitsu-core -
pnpm add kitsu-core
Imports
- deserialise
const deserialise = require('kitsu-core').deserialise;import { deserialise } from 'kitsu-core'; - serialise
import serialise from 'kitsu-core';
import { serialise } from 'kitsu-core'; - camel
import * as kitsuCore from 'kitsu-core'; kitsuCore.camel(...);
import { camel } from 'kitsu-core'; - JsonApiDocument
import { JsonApiDocument } from 'kitsu-core';import type { JsonApiDocument } from 'kitsu-core';
Quickstart
import { deserialise, serialise, camel } from 'kitsu-core';
// Example JSON:API response structure
const jsonApiResponse = {
data: {
type: 'articles',
id: '1',
attributes: {
'title-post': 'JSON:API is great!',
'content-body': 'This is some content.'
},
relationships: {
author: {
data: { type: 'users', id: '9' }
},
comments: {
data: [
{ type: 'comments', id: '5' },
{ type: 'comments', id: '12' }
]
}
}
},
included: [
{
type: 'users',
id: '9',
attributes: {
'full-name': 'John Doe'
}
},
{
type: 'comments',
id: '5',
attributes: {
body: 'First comment'
}
},
{
type: 'comments',
id: '12',
attributes: {
body: 'Second comment'
},
relationships: {
author: {
data: { type: 'users', id: '9' }
}
}
}
]
};
async function runKitsuCoreExample() {
console.log('Original JSON:API Response:', JSON.stringify(jsonApiResponse, null, 2));
// Deserialise the JSON:API response into a plain JavaScript object, applying camelCaseKeys
const deserializedData = await deserialise(jsonApiResponse, { camelCaseKeys: true });
console.log('\nDeserialized Data (camelCaseKeys: true):', JSON.stringify(deserializedData, null, 2));
// Example of using the standalone camel utility
const camelCasedKey = camel('my-kebab-case-key');
console.log('\nCamel cased key:', camelCasedKey); // myKebabCaseKey
// Prepare data for serialization (e.g., after modifying it)
const articleToSerialize = {
id: '1',
type: 'articles',
titlePost: 'Updated Title',
contentBody: 'New content here.',
author: {
id: '9',
type: 'users'
},
comments: [
{ id: '5', type: 'comments' },
{ id: '12', type: 'comments' }
]
};
// Serialize a plain JavaScript object back into JSON:API format
const serializedData = await serialise(articleToSerialize, 'articles', { camelCaseKeys: true });
console.log('\nSerialized Data (camelCaseKeys: true):', JSON.stringify(serializedData, null, 2));
// Demonstrate data hoisting (introduced in v11.1.0)
const hoistedData = await deserialise(jsonApiResponse, {
camelCaseKeys: true,
hoist: ['author'] // Hoist the 'author' relationship directly onto the article object
});
console.log('\nDeserialized Data with Author Hoisted (opt-in since v11.1.0):', JSON.stringify(hoistedData, null, 2));
}
runKitsuCoreExample();