fastify / fastify/fast-json-stringify

oneOf schemas not matching when an object has a custom toJSON() method

Open
#621 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
JavaScript
Stars
3.7k
Forks
226
Avg merge
1d 59m
Merged PRs (30d)
3

Description

### Prerequisites

- [X] I have written a descriptive issue title
- [X] I have searched existing issues to ensure the bug has not already been reported

### Fastify version

4.15.0

### Plugin version

_No response_

### Node.js version

18.12.1

### Operating system

Linux

### Operating system version (i.e. 20.04, 11.3, 10)

Ubuntu 22.10

### Description

`toJSON()` is not called on objects before attempting to match a schema in `oneOf`, resulting in an error "does not match schema definition". When oneOf is not used, the same schema matches, works, and serializes.

### Steps to Reproduce

```js
const fastJson = require('fast-json-stringify');

// schema using oneOf
const stringifyOneOf = fastJson({
description: 'transfer failed.',
oneOf: [
{
type: 'object',
description: 'Invalid withdrawal address provided.',
properties: {
error: { type: 'string', const: 'INVALID_ADDRESS' },
},
required: ['error'],
additionalProperties: false,
},
{
type: 'object',
description: 'Cannot afford this transfer + fee.',
properties: {
error: { type: 'string', const: 'INSUFFICIENT_ACCOUNT_BALANCE' },
balance: {
type: 'object',
description: 'Available balance for this currency.',
properties: {
value: { type: 'string' },
currency: { type: 'string' },
},
additionalProperties: false,
required: ['value', 'currency'],
},
},
required: ['error', 'balance'],
additionalProperties: false,
},
],
});

// schema with no oneOf
const stringify = fastJson({
type: 'object',
description: 'Cannot afford this transfer + fee.',
properties: {
error: { type: 'string', const: 'INSUFFICIENT_ACCOUNT_BALANCE' },
balance: {
type: 'object',
description: 'Available balance for this currency.',
properties: {
value: { type: 'string' },
currency: { type: 'string' },
},
additionalProperties: false,
required: ['value', 'currency'],
},
},
required: ['error', 'balance'],
additionalProperties: false,
});

// custom class with toJSON() method
class Balance {
constructor(value, currency) {
this._value = value;
this._currency = currency;
}

toJSON() {
return {
value: this._value,
currency: this._currency,
};
}
}

const balance = new Balance(100, 'USD');

// will throw 'The value of '#' does not match schema definition.'
console.log(stringifyOneOf({
error: 'INSUFFICIENT_ACCOUNT_BALANCE',
balance,
}));

// stringifies as expected
console.log(stringify({
error: 'INSUFFICIENT_ACCOUNT_BALANCE',
balance,
}));

```

### Expected Behavior

the schema inside `oneOf` should match as it is the same schema that works when used outside of `oneOf` - `toJSON()` not called on objects before matching?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.