📄 js-yaml/examples/handle_unknown_types

File: handle_unknown_types.md | Updated: 11/15/2025

Handling Unknown Types in JS-YAML

This example demonstrates how to handle arbitrary unknown YAML tags using a generic custom type handler.

Overview

Sometimes you need to parse YAML documents that contain tags you don't know in advance. This example shows how to create a wildcard type handler that can capture any unknown tag and preserve it when dumping back to YAML.

The CustomTag Class

class CustomTag {
  constructor(type, data) {
    this.type = type;
    this.data = data;
  }
}

This simple class stores:

  • type: The YAML tag name (e.g., !unknown_scalar_tag)
  • data: The actual data associated with the tag

Creating Wildcard Type Handlers

const tags = [ 'scalar', 'sequence', 'mapping' ].map(function (kind) {
  // first argument here is a prefix, so this type will handle anything starting with !
  return new yaml.Type('!', {
    kind: kind,
    multi: true,
    representName: function (object) {
      return object.type;
    },
    represent: function (object) {
      return object.data;
    },
    instanceOf: CustomTag,
    construct: function (data, type) {
      return new CustomTag(type, data);
    }
  });
});

const SCHEMA = yaml.DEFAULT_SCHEMA.extend(tags);

Key Features

multi: true

Setting multi: true allows the type handler to match any tag that starts with the specified prefix (!).

representName

Returns the tag name to use when dumping the object back to YAML.

construct

Receives both the data and the full tag name, allowing you to preserve the original tag.

Example Usage

const data = `
subject: Handling unknown types in JS-YAML
scalar: !unknown_scalar_tag foo bar
sequence: !unknown_sequence_tag [ 1, 2, 3 ]
mapping: !unknown_mapping_tag { foo: 1, bar: 2 }
`;

const loaded = yaml.load(data, { schema: SCHEMA });

console.log('Parsed as:');
console.log('-'.repeat(70));
console.log(util.inspect(loaded, false, 20, true));

console.log('');
console.log('');
console.log('Dumped as:');
console.log('-'.repeat(70));
console.log(yaml.dump(loaded, { schema: SCHEMA }));

Output

Parsed as:

{
  subject: 'Handling unknown types in JS-YAML',
  scalar: CustomTag {
    type: '!unknown_scalar_tag',
    data: 'foo bar'
  },
  sequence: CustomTag {
    type: '!unknown_sequence_tag',
    data: [ 1, 2, 3 ]
  },
  mapping: CustomTag {
    type: '!unknown_mapping_tag',
    data: { foo: 1, bar: 2 }
  }
}

Dumped as:

subject: Handling unknown types in JS-YAML
scalar: !unknown_scalar_tag 'foo bar'
sequence: !unknown_sequence_tag
  - 1
  - 2
  - 3
mapping: !unknown_mapping_tag
  foo: 1
  bar: 2

Complete Code

'use strict';

const util = require('util');
const yaml = require('../');

class CustomTag {
  constructor(type, data) {
    this.type = type;
    this.data = data;
  }
}

const tags = [ 'scalar', 'sequence', 'mapping' ].map(function (kind) {
  return new yaml.Type('!', {
    kind: kind,
    multi: true,
    representName: function (object) {
      return object.type;
    },
    represent: function (object) {
      return object.data;
    },
    instanceOf: CustomTag,
    construct: function (data, type) {
      return new CustomTag(type, data);
    }
  });
});

const SCHEMA = yaml.DEFAULT_SCHEMA.extend(tags);

const data = `
subject: Handling unknown types in JS-YAML
scalar: !unknown_scalar_tag foo bar
sequence: !unknown_sequence_tag [ 1, 2, 3 ]
mapping: !unknown_mapping_tag { foo: 1, bar: 2 }
`;

const loaded = yaml.load(data, { schema: SCHEMA });

console.log('Parsed as:');
console.log('-'.repeat(70));
console.log(util.inspect(loaded, false, 20, true));

console.log('');
console.log('');
console.log('Dumped as:');
console.log('-'.repeat(70));
console.log(yaml.dump(loaded, { schema: SCHEMA }));

Use Cases

This pattern is useful when:

  • Processing YAML from multiple sources with different custom tags
  • Building tools that need to preserve unknown tags during round-trip parsing
  • Creating generic YAML processors that shouldn't fail on unknown tags
  • Implementing YAML editors that preserve all original tags