Sobes.tech
Middle+

¿Cómo recuperar objetos de JSON de manera que se conserven los metadatos?

sobes.tech AI

Respuesta de la IA

Para restaurar objetos con metadatos guardados desde JSON, se puede usar el método JSON.parse() en combinación con una función reviver. Reviver es una función opcional que se llama para cada par clave-valor durante el análisis de JSON. Permite modificar los valores decodificados antes de que se devuelvan.

Ejemplo de uso de reviver para mantener el tipo:

const jsonString = '{"date": "2023-10-27T10:00:00.000Z", "regexp": "/test/i"}';

const restoredObject = JSON.parse(jsonString, (key, value) => {
  if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/.test(value)) {
    return new Date(value);
  }
  if (typeof value === 'string' && /^\/.+\/[gimyus]*$/.test(value)) {
    try {
       const match = value.match(/^\/(.+)\/([gimyus]*)$/);
       if (match) {
           return new RegExp(match[1], match[2]);
       }
    } catch (e) {
    }
  }
  return value;
});

console.log(restoredObject.date instanceof Date); // true
console.log(restoredObject.regexp instanceof RegExp); // true

Para casos más complejos, donde los metadatos pueden incluir información sobre clases personalizadas u otros tipos, es necesario incluir marcadores explícitos o un esquema en JSON que describa los tipos de datos.

Ejemplo con marcadores explícitos:

{
  "user": {
    "_type": "User",
    "name": "Alice",
    "registrationDate": {
      "_type": "Date",
      "value": "2023-10-26T12:00:00.000Z"
    }
  },
  "settings": {
    "theme": "dark"
  }
}

Y el reviver correspondiente:

class User {
  constructor(name, registrationDate) {
    this.name = name;
    this.registrationDate = registrationDate;
  }
}

const jsonWithMetadata = '{"user": {"_type": "User", "name": "Alice", "registrationDate": {"_type": "Date", "value": "2023-10-26T12:00:00.000Z"}}, "settings": {"theme": "dark"}}';

const restoredObjectWithMetadata = JSON.parse(jsonWithMetadata, (key, value) => {
  if (value && typeof value === 'object' && value._type) {
    switch (value._type) {
      case 'Date':
        return new Date(value.value);
      case 'User':
        return new User(value.name, new Date(value.registrationDate.value));
      default:
        return value;
    }
  }
  return value;
});

console.log(restoredObjectWithMetadata.user instanceof User); // true
console.log(restoredObjectWithMetadata.user.registrationDate instanceof Date); // true

Este método requiere un acuerdo previo sobre la estructura de los metadatos en JSON (por ejemplo, usar la clave _type) y la lógica de recuperación en el reviver para cada tipo. Para objetos complejos, como instancias de clases personalizadas con métodos, se necesita un enfoque más elaborado, posiblemente incluyendo la serialización y deserialización de métodos por separado o usando bibliotecas especializadas. Sin embargo, para tipos estándar y estructuras de datos simples, el reviver es bastante efectivo.