Sobes.tech
Middle+

Come ripristinare gli oggetti da JSON in modo che i metadati siano conservati?

sobes.tech AI

Risposta dell'AI

Per ripristinare oggetti con metadati salvati da JSON, è possibile utilizzare il metodo JSON.parse() in combinazione con una funzione reviver. Reviver è una funzione opzionale chiamata per ogni coppia chiave-valore durante l'analisi JSON. Permette di modificare i valori decodificati prima che vengano restituiti.

Esempio di utilizzo di reviver per mantenere il 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

Per casi più complessi, dove i metadati possono includere informazioni su classi personalizzate o altri tipi, è necessario includere marcatori espliciti o uno schema in JSON che descriva i tipi di dati.

Esempio con marcatori espliciti:

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

E il reviver corrispondente:

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

Questo metodo richiede un accordo preventivo sulla struttura dei metadati in JSON (ad esempio, l'uso della chiave _type) e l'implementazione della logica di ripristino nel reviver per ogni tipo. Per oggetti complessi, come istanze di classi personalizzate con metodi, potrebbe essere necessario un approccio più sofisticato, che potrebbe includere la serializzazione e deserializzazione dei metodi separatamente o l'uso di librerie specializzate. Tuttavia, per tipi standard e strutture di dati semplici, il reviver è abbastanza efficace.