Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
2 tasks done
unek opened this issue Apr 10, 2023 · 1 comment
Open
2 tasks done

Comments

@unek
Copy link

unek commented Apr 10, 2023

Prerequisites

  • I have written a descriptive issue title
  • 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

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?

@ivan-tymoshenko
Copy link
Member

@unek Hi, when you add the oneOf, anyOf or if/then keywords to the schema, FJS validates your input data to match it with one of the options. It validates it before the toJSONcall happens, so it seems like an expected behavior for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants