API y empresas

Por qué actas e identificadores deben viajar como texto y no como números JSON

Un número de acta no es una cantidad. Serializarlo como número puede quitar ceros, alterar dígitos o producir resultados distintos entre lenguajes.

Por Marco Ferreiro ·

Estación de desarrollo con elementos abstractos que representan identificadores digitales

Un número de acta puede estar formado únicamente por dígitos y seguir sin ser un número. No expresa una cantidad, no tiene sentido sumarlo y un cero a la izquierda puede ser parte de su identidad. Modelarlo como number porque “parece numérico” crea errores difíciles de detectar: el JSON continúa siendo válido mientras el valor cambia.

El problema no es exclusivo de JavaScript. El RFC 8259 permite que las implementaciones limiten rango y precisión, y sólo señala interoperabilidad exacta general para enteros dentro de un rango compatible con IEEE 754 binario de doble precisión.

Identidad no equivale a cantidad

Un monto, una velocidad o una cantidad de infracciones tienen semántica numérica. Un acta, expediente, CUIT recibido como referencia, número de tag o código de organismo se usa para igualdad, búsqueda y trazabilidad.

La pregunta práctica es: ¿tiene sentido calcular con este campo? Si la respuesta es no y cada carácter importa, el contrato debería tratarlo como texto aun cuando todos sus caracteres actuales sean dígitos.

Los ceros iniciales desaparecen

JSON no admite ceros iniciales en su gramática de números. El identificador 001234 no puede expresarse como número conservando esa forma: al parsearlo o regenerarlo se convierte en 1234.

Agregar relleno después exige conocer la longitud exacta para cada autoridad. Esa longitud puede cambiar o coexistir con series diferentes. Guardar el valor original como string evita inventar una reconstrucción.

La precisión tiene un límite visible

El RFC 8259 advierte que distintas implementaciones pueden imponer límites y que los enteros interoperables de forma exacta con software basado en doble precisión quedan acotados. ECMAScript define Number.MAX_SAFE_INTEGER como 9.007.199.254.740.991.

Un identificador más largo puede parsearse sin error y redondearse. Dos valores consecutivos terminan comparándose como iguales. Convertir el resultado a string después no recupera el dígito perdido.

Un round-trip que debe formar parte de los tests

La prueba mínima consiste en enviar y devolver sin cambios estos casos sintéticos:

El valor debe ser idéntico byte a byte después de pasar por servidor, cola, base, cliente y exportación. Probar sólo el endpoint productor deja conversiones invisibles en etapas intermedias.

El esquema debe decirlo con claridad

En OpenAPI, un identificador puede declararse como type: string, con patrón y límites de longitud. JSON Schema permite sumar restricciones sin convertirlo en cantidad. Ejemplos ficticios ayudan a que los generadores de SDK creen tipos correctos.

No conviene usar format: int64 como sustituto universal. Aunque documente intención, algunos clientes lo mapearán a un tipo exacto y otros a un number limitado. Además, un identificador puede superar 64 bits o incorporar letras mañana.

Migrar sin romper clientes

Cambiar un campo público de number a string es un cambio de contrato. Una migración segura puede agregar un campo nuevo, anunciar deprecación, actualizar SDK y fixtures, y medir qué versión usa cada cliente sin registrar valores sensibles.

Aceptar ambos tipos en la entrada puede ser útil durante un plazo acotado, pero la salida debe ser canónica. Si cada respuesta alterna según la fuente, se traslada el problema a todas las integraciones.

Bases, CSV y planillas también importan

La columna interna debe conservar el mismo principio. Una base puede convertir cadenas a enteros; un CSV puede ser interpretado automáticamente por una planilla y mostrar notación científica. Exportar con un esquema, ofrecer checksum y documentar el tipo reduce esas sorpresas.

Los logs no necesitan imprimir el identificador completo para probar el flujo. Es preferible usar un hash o referencia interna controlada y reservar el valor original para el contexto autorizado.

Validar la entrada sin volverla rígida

Declarar string no significa aceptar cualquier contenido. El esquema puede definir longitud máxima, conjunto de caracteres y si se permiten guiones, sin asumir una longitud única para todas las jurisdicciones. La validación debe ocurrir en el borde y devolver un error entendible, no convertir silenciosamente el valor.

Los espacios externos pueden eliminarse cuando la regla está documentada; los internos, prefijos y ceros necesitan más cuidado. Si la fuente cambia su formato, conviene guardar el original y generar una representación normalizada separada. De ese modo se puede actualizar la regla sin perder la cadena que recibió la integración.

Compatibilidad con lenguajes diferentes

JavaScript suele concentrar la atención por su tipo number, pero otros lenguajes también eligen enteros de tamaño fijo o generan modelos desde OpenAPI. Las pruebas deben ejecutar clientes reales o, como mínimo, fixtures en los lenguajes soportados.

Una documentación con un ejemplo corto como 123 no revela el riesgo. Incluir ceros iniciales y valores cercanos al límite fuerza a los SDK y revisores a comprobar que el contrato conserva identidad, no sólo que el JSON parsea.

Contratos previsibles para infracciones

Una API de infracciones conecta fuentes con formatos heterogéneos. La normalización no debe cambiar la identidad para hacerla “más cómoda”. Preservar texto original, exponer un identificador canónico separado y declarar la procedencia permite corregir mapeos sin perder el vínculo.

El criterio es simple: si un campo nombra algo, tratémoslo como nombre. Que esté compuesto por dígitos es un detalle de formato, no una invitación a hacer aritmética.

Metodología

Alcance
Contratos JSON que transportan números de acta, expediente, dispositivo o referencias externas sin semántica aritmética.
Unidad de análisis
Un valor que realiza un recorrido de serialización y parseo entre productores y clientes de distintos lenguajes.
Cobertura
Se aplican las reglas públicas de JSON, ECMAScript, OpenAPI y JSON Schema; cada integración debe sumar pruebas con sus propios límites.

Limitaciones

Fuentes

Preguntas frecuentes

¿Un identificador compuesto sólo por dígitos puede ser string?

Sí. El tipo describe su función, no su apariencia. Si el valor identifica una entidad y no representa una cantidad, string suele ser el contrato correcto.

¿Convertir a string en el frontend corrige la pérdida?

No si el parser ya recibió y redondeó el número. La precisión debe preservarse desde el productor y durante todo el recorrido, incluida la base, la cola y el archivo exportado.

¿Conviene aceptar number y string al mismo tiempo?

Sólo como migración explícita y temporal. La respuesta canónica debe tener un tipo estable; de lo contrario cada cliente termina normalizando de manera diferente.

Notas relacionadas

Auditoría de accesos: qué se registra

Un log operativo explica por qué falló una consulta. Un registro de accesos explica quién vio qué información y con qué habilitación. Son artefactos distintos y conviene no mezclarlos.