Leer y escribir YAML en un archivo en Node.js/JavaScript

YAML se ha vuelto bastante popular recientemente en la industria del desarrollo. En este artículo, veremos cómo puede usar archivos YAML con una aplicación Node.js/JavaScript leyéndolos y escribiendo en ellos.

Introducción

En los últimos años, YAML, que significa YAML Ain't Markup Language, se ha vuelto muy popular para almacenar datos de manera serializada, generalmente archivos de configuración. Dado que YAML es esencialmente un formato de datos, la especificación YAML es bastante breve. Por lo tanto, la única funcionalidad requerida de las bibliotecas YAML es la capacidad de analizar o generar archivos con formato YAML.

En este artículo, veremos cómo puede usar [YAML] (https://en.wikipedia.org/wiki/YAML) con una aplicación Node.js. Comenzaremos viendo cómo se almacenan los datos en un archivo YAML, y luego cargaremos esos datos en un objeto JavaScript. Por último, aprenderemos cómo almacenar un objeto JavaScript en un archivo YAML.

Hay algunas bibliotecas de nodos populares que se usan para analizar y generar YAML: Yaml y [js-yaml](https://www.npmjs.com/package /js-yaml). js-yaml es la más popular de las dos bibliotecas, por lo que nos centraremos en este artículo.

Antes de continuar, hay algunos requisitos previos para este tutorial. Debe tener una comprensión básica de la sintaxis de JavaScript, específicamente para el tiempo de ejecución de Node.js. También querrá tener Node.js y NPM instalados en su sistema para seguir adelante. Aparte de eso, el tutorial es bastante simple y fácil de seguir para principiantes.

Instalación

Como con cualquier paquete de Node, la instalación es bastante simple usando NPM:

1
$ npm install js-yaml

Solo asegúrese de usar los indicadores correctos para guardar la dependencia en su archivo package.json. Por ejemplo, si js-yaml solo se usa con fines de desarrollo, entonces use --save-dev; de lo contrario, use --save si se usa en el entorno de producción de su aplicación.

Puede verificar que esté correctamente instalado abriendo REPL desde el mismo directorio e importando el paquete con lo siguiente:

1
2
3
$ node
> const yaml = require('js-yaml')
>

La biblioteca js-yaml también es compatible con el uso de CLI, lo que le permite inspeccionar archivos YAML desde la línea de comandos. Puede habilitar esto instalando el paquete globalmente:

1
$ npm install -g js-yaml

Leer archivos YAML en Node.js

Comenzaremos leyendo un archivo con formato YAML y analizándolo en un objeto JS. Por el bien de este tutorial, digamos que tenemos un archivo, data.yaml, que tiene los siguientes contenidos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
--- # Article data
article:
title: "Reading and Writing YAML to a File in Node.js/JavaScript"
url_path: "/reading-and-writing-yaml-to-a-file-in-node-js-javascript"
domain: "wikihtp.com"
port: 443
is-https: true
meta:
  published-at: "Nov. 1st, 2019"
  author:
    name: "Scott Robinson"
    contact: "[correo electrónico protegido]"
  tags:
    - javascript
    - node.js
    - web development

Para leer y analizar este archivo, usaremos el método .safeLoad():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// read.js
const fs = require('fs');
const yaml = require('js-yaml');

try {
    let fileContents = fs.readFileSync('./data.yaml', 'utf8');
    let data = yaml.safeLoad(fileContents);

    console.log(data);
} catch (e) {
    console.log(e);
}

Ejecutar este código generará lo siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ node read.js
{ title: 'Reading and Writing YAML to a File in Node.js/JavaScript',
  'url path': '/reading-and-writing-yaml-to-a-file-in-node-js-javascript',
  domain: 'wikihtp.com',
  port: 443,
  'is-https': true,
  meta:
   { 'published-at': 'Nov. 1st, 2019',
     author: { name: 'Scott Robinson', contact: '[correo electrónico protegido]' },
     tags: [ 'javascript', 'node.js', 'web development' ] } }

Puede ver que los datos en el archivo YAML ahora se convierten en objetos y literales JS en la misma estructura que el archivo.

Se recomienda el método .safeLoad() para analizar contenido YAML, ya que es seguro para datos que no son de confianza. Una limitación que vale la pena señalar es que este método no admite fuentes de varios documentos. Si está familiarizado con YAML, sabrá que YAML puede contener múltiples "documentos" dentro de un solo archivo, que están separados con la sintaxis ---. Por ejemplo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
--- # Programming language
  language: "JavaScript"
  created-at: "December 4, 1995"
  domain: "wikihtp.com"
  creator: "Brendan Eich"
--- # Website
  domain: "wikipedia.org"
  created-at: "January 15, 2001"
  num-languages: 304
  num-articles: 51360771
  creator:
    - Jimmy Wales
    - Larry Sanger

Cargar este archivo con .safeLoad() generará una excepción. En su lugar, deberías usar el método .safeLoadAll(), así:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// read-all.js
const fs = require('fs');
const yaml = require('js-yaml');

try {
    let fileContents = fs.readFileSync('./data-multi.yaml', 'utf8');
    let data = yaml.safeLoadAll(fileContents);

    console.log(data);
} catch (e) {
    console.log(e);
}

Esto da como resultado una serie de documentos YAML analizados:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ node read-all.js
[ { language: 'JavaScript',
    'created-at': 'December 4, 1995',
    domain: 'wikihtp.com',
    creator: 'Brendan Eich' },
  { domain: 'wikipedia.org',
    'created-at': 'January 15, 2001',
    'num-languages': 304,
    'num-articles': 51360771,
    creator: [ 'Jimmy Wales', 'Larry Sanger' ] } ]

Otro método que vale la pena mencionar es el método .load(), que es muy similar a .safeLoad(), excepto que admite todos Tipos de esquema YAML. Los tipos adicionales compatibles son específicos de JavaScript (!!js/undefined, !!js/regexp y !!js/function) y debe confiar absolutamente en los datos de estos archivos YAML, ya que pueden cargarse sin confianza. código.

Por ejemplo, una función se puede definir en YAML como la siguiente:

1
'toString': !<tag:yaml.org,2002:js/function> function() {console.log('Malicious code execuited!');}

Esa etiqueta le dice a nuestra biblioteca YAML que la analice como una función, que luego se puede ejecutar más tarde. Como se señala en la documentación, un método común que se ejecuta en objetos JS es toString, que podemos explotar así:

1
2
3
4
5
6
// unsafe.js
const yaml = require('js-yaml');

let yamlStr = "'toString': !<tag:yaml.org,2002:js/function> function() {console.log('Malicious code execuited!');}";
let loadedYaml = yaml.load(yamlStr) + '';
console.log(loadedYaml);

Y ejecutar este código muestra que el método console.log sí se ejecuta:

1
2
3
$ node unsafe.js 
Malicious code execuited!
undefined

Escribir YAML en archivos en Node.js

Ahora que sabe cómo leer archivos YAML con Node.js, veamos cómo podemos escribir objetos/datos de JavaScript en un archivo YAML.

Para este ejemplo, usaremos el siguiente objeto JS, que puede reconocer de los ejemplos anteriores:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
let data = {
    title: 'Reading and Writing YAML to a File in Node.js/JavaScript',
    'url path': '/reading-and-writing-yaml-to-a-file-in-node-js-javascript',
    domain: 'wikihtp.com',
    port: 443,
    'is-https': true,
    meta: {
        'published-at': 'Nov. 1st, 2019',
        author: {
            name: 'Scott Robinson',
            contact: '[correo electrónico protegido]'
        },
        tags: [
            'javascript', 'node.js', 'web development'
        ]
    }
};

Para serializar este objeto y guardarlo en un archivo con formato YAML, usaremos el método .safeDump(), que nuevamente usa DEFAULT_SAFE_SCHEMA de js-yaml:

1
2
3
4
5
6
7
8
// write.js
const fs = require('fs');
const yaml = require('js-yaml');

let data = { /* Same as above */};

let yamlStr = yaml.safeDump(data);
fs.writeFileSync('data-out.yaml', yamlStr, 'utf8');

Ejecutar este código escribirá un archivo YAML similar a este:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
title: Reading and Writing YAML to a File in Node.js/JavaScript
url path: /reading-and-writing-yaml-to-a-file-in-node-js-javascript
domain: wikihtp.com
port: 443
is-https: true
meta:
  published-at: 'Nov. 1st, 2019'
  author:
    name: Scott Robinson
    contact: [correo electrónico protegido]
  tags:
    - javascript
    - node.js
    - web development

Este resultado es casi idéntico al YAML original que leímos anteriormente en este artículo, excepto que el separador de documentos (---) no está incluido.

Tipos de datos {#tipos de datos}

Es importante tener en cuenta que no todos los tipos de datos de JavaScript se pueden serializar directamente en YAML y viceversa. En algunos casos, se usará el tipo de datos más cercano cuando sea posible si no se admite directamente. Por ejemplo, un tipo YAML !!seq se analizará como una matriz de JavaScript.

Según la documentación js-yaml, se admiten los siguientes tipos de datos:

Ejemplo de tipo YAML Tipo JS


!!null '' nulo !!bool verdadero bool !!int 3 número !!flotante 3.1415 número !!binario c3RhY2thYnVzZS5jb20= búfer !!marca de tiempo '2013-08-15' fecha !!omap [ ... ] matriz de pares clave-valor !!pares [ ... ] arreglo o pares de arreglos !!set { ... } matriz de objetos con claves dadas y valores nulos !!str cadena '...' !!seq [ ... ] matriz !!mapa { ... } objeto

Como se mencionó anteriormente, también se pueden admitir otros tipos específicos de JS, pero solo si no está utilizando los métodos "seguros".

Conclusión

YAML es un formato cada vez más popular que se usa para estructurar datos para aplicaciones, normalmente como archivos de configuración, pero también como reemplazo de cualquier cosa para la que se use JSON. Debido a su alta flexibilidad y sintaxis fácil de leer, está reemplazando rápidamente a JSON en muchos proyectos, aunque ambos todavía tienen su lugar.

En este artículo mostramos cómo puede usar la biblioteca js-yaml para analizar archivos YAML en objetos JavaScript en Node.js y cómo puede serializar objetos JavaScript en un archivo YAML. También mostramos qué tipos de JS se usan para varios tipos de datos YAML. Para obtener más detalles sobre esta biblioteca, consulte la [documentación oficial] (https://www.npmjs.com/package/js-yaml).