¿Por qué las funciones JSON.stringify y JSON.parse en JavaScript no fueron diseñadas para ser idempotentes?

No estoy realmente seguro de a dónde vas con idempotencia, aquí.

Si estás hablando de idempotencia matemática, como:

identidad (identidad (identidad (x))) === identidad (x)

Eso es genial, pero no podemos vivir en ese mundo todo el tiempo.

Un mundo diferente, y uno que vale la pena considerar es el que la mayoría de los desarrolladores de sistemas consideran idempotentes:

GET / blogs / abc123

Que produce

Puede llamar a esa URL varias veces, en paralelo, y obtener la misma respuesta; o al menos, la llamada de la URL no afecta el contenido devuelto, independientemente de la cantidad de veces que se llame.

… pero mira lo que no consideramos idempotente en este caso:

GET / blogs / abc123> GET / blogs / $ {1}> GET / blogs $ {1}

Sí, esto está lleno de pseudocódigo terrible.

La primera vez que lo llama, el valor de la ID es “abc123”.
La segunda vez que lo llama, el valor de la ID es:

Algunas publicaciones de blog

La tercera vez que lo llame, su salida final será algo así como:

404 – No encontrado

Tenga en cuenta que no está poniendo exactamente el mismo valor; ergo, no estás obteniendo el valor apropiado.

Lo hacen, sin embargo lo consideran idempotente, porque puedes hacer esto:

id = “abc123”
GET / blogs / $ id
GET / blogs / $ id
GET / blogs / $ id
GET / blogs / $ id

Y cada vez que realiza esa llamada, su salida es la misma que la primera vez que realizó la llamada (dentro de lo razonable), o como mínimo, la primera llamada no tuvo una influencia apreciable en la salida de la cuarta.

Lo mismo sería cierto para las bases de datos:

seleccione * de personas donde firstName = ‘Bob’

Te da una lista de bobs.

Alimentando eso de nuevo, obtienes

seleccione * de las personas donde [
{firstName: “Bob”, lastName: “Hope”},
{firstName: “Bob”, lastName: “Newheart”},
{nombre: “Bob”, apellido: “McKenzie”},
]

Tenga en cuenta que estas son dos declaraciones excepcionalmente diferentes.

Así que de vuelta a JSON.parse . De hecho, estoy totalmente de acuerdo en que debe devolver su entrada, si su entrada no es una cadena. Pero esa no es realmente la forma en que operan los programas OO creados por desarrolladores Java. No es que Crockford fuera cualquiera de esas cosas, pero la biblioteca JSON no estaba hecha para programadores de FP incondicionales. Tampoco es como si fuera una mónada. Lanzar errores fue solo cómo se manejaron las cosas (y aún lo son, en muchos casos).

JSON.stringify No creo que pueda estar más en desacuerdo con respecto a que debería ser idempotente. Eso es como pedirle a POST que se haga idempotente. O INSERTAR. O escribir / eco.

Hay muchas razones para querer codificar una cadena como el valor raíz de una carga útil JSON.

Hay razones por las que una aplicación puede elegir codificar cadenas escapadas como parte de sus datos de dominio (que generalmente es una mala elección, pero sigue siendo una necesidad válida si eso es lo que tenían que hacer para que su aplicación despegara).

¿En cuántos idiomas va a cambiar la serialización JSON? ¿Cuántas bases de datos / almacenes de datos / etcétera?

Cuando escribo a mano archivos JSON, como el archivo de manifiesto package.json, o alguna configuración de servidor similar, ahora necesito recordar que todos mis archivos también deben cambiarse …

… excepto que si todos mis archivos también se cambian, eso significa que ya no coinciden con la notación de objetos JavaScript.

Mientras tanto, puedo afirmar, durante todo el día que:

const obj = {a: 1, b: 2};

const a = JSON.stringify (obj);
const b = JSON.stringify (obj);
const c = JSON.stringify (obj);

a === b && a === c && b === c;

En informática, una operación idempotente es aquella que no tiene ningún efecto adicional si se llama más de una vez con los mismos parámetros de entrada. Por ejemplo, eliminar un elemento de un conjunto puede considerarse una operación idempotente en el conjunto.

En matemáticas, una operación idempotente es aquella en la que f (f (x)) = f (x). Por ejemplo, la función abs () es idempotente porque abs (abs (x)) = abs (x) para todas las x.

En Javascript si llamamos

JSON.stringify (objeto) -> convierte el objeto en texto JSON y almacena ese texto JSON en una cadena.

JSON.stringify (JSON.stringify (objeto)) -> el stringify externo se aplica en la cadena resultante que resulta en ‘\’ extra en su objeto, lo cual no es un comportamiento de una función idempotente ideal.

¡Es por eso que no se considera como una función Idempotente!

¿Por qué las funciones JSON.stringify y JSON.parse en JavaScript no fueron diseñadas para ser idempotentes?

No tendría ningún sentido. Como sabes,

let str = ‘foo’;
JSON.stringify (str); // ‘”foo”‘
JSON.stringify (JSON.stringify (str)); // ‘”\\” foo \\ “”‘

No idempotente. Pero considere lo que significaría si fuera idempotente.

let ob = {foo: ‘bar’};
let str = idempotentStringify (ob);

Si la stringificación es idempotente, debe ser el caso de que [math] \ forall [/ math] x ,

idempotentStringify (x) === idempotentStringify (idempotentStringify (x))

Entonces, ¿cómo distingue entre una cadena que representa un objeto serializado y una cadena que simplemente contiene el texto correspondiente a un objeto serializado? Cuando intenta analizar una cadena, ¿cómo sabe si deserializar un objeto o devolver la cadena de manera idempotente?