100 % locale — i tuoi dati non lasciano mai il tuo browser

JSON in io-ts — decodifica e ottieni il tipo

Trasforma un campione JSON in codec io-ts. Un codec per oggetto, dichiarato prima dell’uso, e TypeOf ti dà il tipo statico da quella dichiarazione.

Istantaneo Privato Zero cookie

Input JSON

Output io-ts

Che cosa fa questo strumento

Un campione JSON diventa codec io-ts, un const per oggetto.

{ "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,
});

I figli sono dichiarati per primi: i codec sono valori a runtime, uno deve esistere prima che un altro lo nomini. Un array alla radice ottiene il proprio codec — export const Users = t.array(UsersItem); — invece di lasciartelo scrivere.

t.Int è marcato, e si vede

t.Int è un raffinamento di t.number che porta una prova di integralità. t.TypeOf<typeof Root> dà quindi { id: Int; … }, non { id: number; … }. Un Int va dove ci si aspetta un number; il contrario richiede un decode. Se quell’attrito non vale il controllo d’intero nella tua base, t.number è una sostituzione di una parola.

Quale dei due ottieni dipende da come è scritto il numero: 3 dà t.Int, 10.0 dà t.number. Fino a poco fa anche 10.0 dava t.Int, e il codec rifiutava poi 10.5 — il record successivo. Era un difetto vero, trovato scrivendo queste pagine e corretto.

Ciò che un codec lascia passare

t.type controlla ciò che conosce e ignora il resto. Una risposta con tre campi in più si decodifica pulita. È la semantica d’interfaccia di io-ts, ed è il predefinito giusto per leggere l’API di qualcun altro — ma se una chiave inattesa deve essere un errore, avvolgi la stessa forma in t.strict, o in t.exact per toglierla.

Decodificare, in una riga

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

const result = Root.decode(payload);
if (isRight(result)) { /* result.right è tipizzato */ }

PathReporter.report(result) trasforma un fallimento in percorsi leggibili — comodo la prima volta che un codec rifiuta un carico che credevi giusto.

Tutto è obbligatorio

Ogni chiave del campione finisce in t.type, dunque obbligatoria. io-ts scrive l’opzionalità in un t.partial a parte, unito con t.intersection. Ripartire le chiavi tra le due metà è un’affermazione sull’API; un documento non può farla al posto tuo.

Privato per progettazione

Tutto viene eseguito localmente nel browser con JavaScript. I tuoi dati non vengono mai caricati, quindi lo strumento è sicuro per contenuti sensibili e funziona anche offline.

Domande frequenti

`t.type` rifiuta le proprietà in più?
No. `t.type` valida le proprietà che conosce e lascia passare il resto: è ciò che io-ts chiama codec d’interfaccia. `t.exact` toglie le eccedenti, `t.strict` le rifiuta. Il generatore emette `t.type` perché un campione non può dire quale dei tre vuoi — è una decisione sulla tua API.
Perché `t.TypeOf` mi dà `Int` e non `number`?
`t.Int` è un tipo marcato: un `Int` è un `number` che porta la prova di essere stato validato come intero. Assegnare un `Int` a un `number` funziona; il contrario richiede un decode. Se preferisci numeri semplici ovunque, sostituisci `t.Int` con `t.number` e rinuncia al controllo d’intero.
Tutti i campi sono obbligatori?
Sì, ed è quanto un solo campione sostiene. io-ts scrive l’opzionalità con `t.partial`, di solito combinato in `t.intersection([t.type({…}), t.partial({…})])`. Ripartire le chiavi tra le due metà presuppone di conoscere l’API, non di leggere un documento: l’intersezione resta a te.

Convertitori correlati