1.0.1 • Published 7 months ago

json-decode v1.0.1

Weekly downloads
3
License
MIT
Repository
github
Last release
7 months ago

json-decode

json-decode is a small library built to help decode unknown data into known types.

The concept of serialisation/deserialisation is baked into many real languages but unfortunately not into JavaScript. This often leads to us developers making the assumption in our code that when receiving data across a boundary, it will have the shape we expect.

json-decode exists to help us validate those assumptions at runtime.

Installation

With pnpm

pnpm install json-decode

With yarn

yarn install json-decode

With npm

npm install json-decode

Usage

Decoding a string

import { string } from "json-decode";

string('hello world'); // 'hello world'
string(1); // throws a DecodeError

You'll find the same behaviour for all of the primitive decoders.

Decoding an object

Let's imagine we have an API request to fetch a book and we need to deserialise it.

import { Decoder, field, number, string } from "json-decode";

type Book = {
  id: number;
  title: string;
  author: string;
};

const decodeBook: Decoder<Book> = json => ({
  id: field('name', number)(json),
  title: field('title', string)(json),
  author: field('author', string)(json),
})

function getBook(): Promise<Book> {
  return fetch('https://example.com/book/1')
    .then((response) => response.json())
    .then((json) => decodeBook(json));
}

Once again, it's worth noting that this will throw an error if the data doesn't match the shape we expect. In that case, you have a couple of options at your disposal: 1. Catch the DecodeError and handle it however you see fit:

import { DecodeError } from "json-decode"; 

try {
  decodeBook(json); 
} catch (error) {
  if (error instanceof DecodeError) {
    // handle the error 
  } else {
    // is this even a book?
  }
}
  1. Make use of the nullable decoder, like so:
import { Decoder, field, number, string, nullable } from "json-decode";


const decodeBook: Decoder<Book> = json => ({
  id: field("name", number)(json),
  title: field("title", string)(json),
  author: field("author", string)(json)
});

// This will return `null` if the data cannot be decoded into a `Book`
const decodeNullableBook: Decoder<Book | null> = nullable(decodeBook);

Decoding an object with an optional property

In this example we extend the book type to have an optional publisher property, containing some other data which we decode.

import { Decoder, field, number, string } from "json-decode";

type Publisher = {
  id: bigint;
  name: string;
  address?: string;
};
type Book = {
  id: number;
  title: string;
  author: string;
  publisher?: Publisher
};

const decodePublisher: Decoder<Publisher> = (json) => ({
  id: field('id', bigint)(json),
  name: field('name', string)(json),
  address: optional(field('address', string))(json),
});

const decodeBook: Decoder<Book> = (json) => ({
  id: field('name', number)(json),
  title: field('title', string)(json),
  author: field('author', string)(json),
  publisher: field('publisher', optional(decodePublisher))(json),
});

Decoding an array

import { Decoder, array, field, number, string } from "json-decode";

array(number)([1, 2, 3]); // [1, 2, 3]
array(number)([1, 2, '3']); // throws a DecodeError
0.0.1

7 months ago

1.0.1

7 months ago

0.0.5

8 months ago

1.0.0

7 years ago