JSON encadena un conjunto


102

¿Cómo un JSON.stringify () un conjunto ?

Cosas que no funcionaron en Chromium 43:

var s = new Set(['foo', 'bar']);

JSON.stringify(s); // -> "{}"
JSON.stringify(s.values()); // -> "{}"
JSON.stringify(s.keys()); // -> "{}"

Esperaría obtener algo similar al de una matriz serializada.

JSON.stringify(["foo", "bar"]); // -> "["foo","bar"]"

Respuestas:


108

JSON.stringify no funciona directamente con conjuntos porque los datos almacenados en el conjunto no se almacenan como propiedades.

Pero puede convertir el conjunto en una matriz. Entonces podrá secuenciarlo correctamente.

Cualquiera de los siguientes servirá:

JSON.stringify([...s]);
JSON.stringify([...s.keys()]);
JSON.stringify([...s.values()]);
JSON.stringify(Array.from(s));
JSON.stringify(Array.from(s.keys()));
JSON.stringify(Array.from(s.values()));

2
Iba a proponer Array.from(). Pero esto parece idiomáticamente mejor.
TaoPR

3
Solo para agregar alguna referencia, MDN tiene algunos ejemplos de esta y otras técnicas relacionadas
Amit

5
Una lista de comprensión también podría funcionar:JSON.stringify([_ for (_ of s)])
Whymarrh

1
Todas son excelentes formas de hacerlo, lamentablemente no funcionan en Chromium 43 ya que spread y Array.from aún no están implementados. Parece Babel al rescate.
MitMaro

2
Una propuesta actual para mejorar el valor predeterminado de Set.prototype.toJSON: github.com/DavidBruant/Map-Set.prototype.toJSON
Oncle Tom

34

Utilice este JSON.stringifysustituto:

(porque toJSONes un artefacto heredado, y un mejor enfoque es usar uno personalizadoreplacer , consulte https://github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16 )

function Set_toJSON(key, value) {
  if (typeof value === 'object' && value instanceof Set) {
    return [...value];
  }
  return value;
}

Luego:

const fooBar = { foo: new Set([1, 2, 3]), bar: new Set([4, 5, 6]) };
JSON.stringify(fooBar, Set_toJSON)

Resultado:

"{"foo":[1,2,3],"bar":[4,5,6]}"

5
hay una versión JSON.stringify(fooBar, (key, value) => value instanceof Set ? [...value] : value)
abreviada

¿El reanimador correspondiente se deja como ejercicio para el lector? ;-)
Robert Siemer

7

Si bien todo lo anterior funciona, le sugiero que establezca una subclase y agregue un toJSONmétodo para asegurarse de que se encadena correctamente. Especialmente si vas a hacer cuerdas con frecuencia. Utilizo conjuntos en mis tiendas Redux y necesitaba asegurarme de que esto nunca fuera un problema.

Esta es una implementación básica. Nombrar es solo para ilustrar el punto, elija su propio estilo.

class JSONSet extends Set {
    toJSON () {
        return [...this]
    }
}

const set = new JSONSet([1, 2, 3])
console.log(JSON.stringify(set))

4
No recomendaría este enfoque ya que toJSONse considera una característica heredada. Una propuesta para agregar toJSONa ambos sety mapfue rechazada: github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16
MitMaro

constructorNo es necesario anular .
Justin Johnson
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.