100 % local — vos données ne quittent jamais votre navigateur

JSON en io-ts — décodez et récupérez le type

Transformez un échantillon JSON en codecs io-ts. Un codec par objet, déclaré avant usage, et TypeOf vous rend le type statique depuis la même déclaration.

Instantané Privé Zéro cookie

Entrée JSON

Sortie io-ts

Ce que fait cet outil

Un échantillon JSON devient des codecs io-ts, un const par objet.

{ "id": 1, "name": "Ada", "address": { "city": "Paris" } }
import * as t from "io-ts";

export const Address = t.type({
  city: t.string,
});

export const Root = t.type({
  id: t.Int,
  name: t.string,
  address: Address,
});

Les enfants sont déclarés d’abord : les codecs sont des valeurs d’exécution, l’un doit exister avant qu’un autre le mentionne. Un tableau à la racine obtient son propre codec — export const Users = t.array(UsersItem); — au lieu de vous laisser l’écrire.

t.Int est un type marqué, et cela se voit

t.Int est un raffinement de t.number porteur d’une preuve d’intégralité. t.TypeOf<typeof Root> rend donc { id: Int; … }, pas { id: number; … }. Un Int va partout où l’on attend un number ; l’inverse demande un décodage. Si ce frottement ne vaut pas le contrôle d’entier dans votre base, t.number est un remplacement d’un mot.

Lequel des deux vous obtenez dépend de l’écriture du nombre : 3 donne t.Int, 10.0 donne t.number. Jusqu’à peu, 10.0 donnait aussi t.Int, et le codec refusait alors 10.5 — l’enregistrement suivant. C’était un vrai défaut, trouvé en écrivant ces pages et corrigé.

Ce qu’un codec laisse passer

t.type contrôle ce qu’il connaît et ignore le reste. Une réponse comportant trois champs de plus se décode proprement. C’est la sémantique d’interface d’io-ts, et c’est le bon défaut pour lire l’API de quelqu’un d’autre — mais si une clé inattendue doit être une erreur, enveloppez la même forme dans t.strict, ou dans t.exact pour la retirer.

Décoder, en une ligne

import { isRight } from "fp-ts/Either";

const result = Root.decode(payload);
if (isRight(result)) { /* result.right est typé */ }

PathReporter.report(result) transforme un échec en chemins lisibles — utile la première fois qu’un codec refuse une charge que vous croyiez correcte.

Tout est obligatoire

Chaque clé de l’échantillon atterrit dans t.type, donc en obligatoire. io-ts écrit l’optionalité dans un t.partial séparé, joint par t.intersection. Répartir vos clés entre les deux moitiés est une affirmation sur l’API ; un document ne peut pas la porter à votre place.

Confidentiel par conception

Tout s’exécute localement dans votre navigateur en JavaScript. Vos données ne sont jamais envoyées sur un serveur, ce qui rend l’outil sûr pour des contenus sensibles, et il fonctionne hors ligne.

Questions fréquentes

`t.type` refuse-t-il les propriétés en trop ?
Non. `t.type` valide les propriétés qu’il connaît et laisse passer le reste : c’est ce qu’io-ts appelle un codec d’interface. `t.exact` retire les surplus, `t.strict` les refuse. Le générateur émet `t.type` parce qu’un échantillon ne peut pas dire lequel des trois vous voulez — c’est une décision sur votre API.
Pourquoi `t.TypeOf` me rend-il `Int` et non `number` ?
`t.Int` est un type marqué : un `Int` est un `number` porteur d’une preuve d’intégralité. Affecter un `Int` à un `number` fonctionne ; l’inverse demande un décodage. Si vous préférez des nombres simples partout, remplacez `t.Int` par `t.number` et renoncez au contrôle d’entier.
Tous les champs sont-ils obligatoires ?
Oui, et c’est ce qu’un seul échantillon permet d’affirmer. io-ts écrit l’optionalité avec `t.partial`, en général combiné en `t.intersection([t.type({…}), t.partial({…})])`. Répartir les clés entre les deux moitiés suppose de connaître l’API, pas de lire un document : le générateur vous laisse l’intersection.

Convertisseurs associés