NatLabs / serde

Serialization and Deserialization library for motoko
MIT License
16 stars 4 forks source link
candid json motoko parser serialization

serde for Motoko

An efficient serialization and deserialization library for Motoko.

The library contains four modules:

Getting Started

Installation

mops

  1. Install mops.
  2. Inside your project directory, run:
mops install serde

Usage

To start, import the necessary modules:

import { JSON; Candid; CBOR; UrlEncoded } from "mo:serde";

JSON

The following code can be used for converting data between the other modules (Candid and URL-Encoded Pairs).

Example: JSON to Motoko

  1. Defining Data Type: This critical step informs the conversion functions (from_candid and to_candid) about how to handle the data.

    Consider the following JSON data:

    [
     {
       "name": "John",
       "id": 123
     },
     {
       "name": "Jane",
       "id": 456,
       "email": "jane@gmail.com"
     }
    ]

    The optional email field translates to:

    type User = {
       name: Text;
       id: Nat;
       email: ?Text;
    };
  2. Conversion: a. Parse JSON text into a candid blob using JSON.fromText. b. Convert the blob to a Motoko data type with from_candid.

    let jsonText = "[{\"name\": \"John\", \"id\": 123}, {\"name\": \"Jane\", \"id\": 456, \"email\": \"jane@gmail.com\"}]";
    
    let #ok(blob) = JSON.fromText(jsonText, null); // you probably want to handle the error case here :)
    let users : ?[User] = from_candid(blob);
    
    assert users == ?[
       {
           name = "John";
           id = 123;
           email = null;
       },
       {
           name = "Jane";
           id = 456;
           email = ?"jane@gmail.com";
       },
    ];

Example: Motoko to JSON

  1. Record Keys: Collect all unique record keys from your data type into an array. This helps the module convert the record keys correctly instead of returning its hash.

    let UserKeys = ["name", "id", "email"];
  2. Conversion:

    let users: [User] = [
       {
           name = "John";
           id = 123;
           email = null;
       },
       {
           name = "Jane";
           id = 456;
           email = ?"jane@gmail.com";
       },
    ];
    
    let blob = to_candid(users);
    let json_result = JSON.toText(blob, UserKeys, null);
    
    assert json_result == #ok(
        "[{\"name\": \"John\",\"id\": 123},{\"name\": \"Jane\",\"id\":456,\"email\":\"jane@gmail.com\"}]"
    );

Example: Renaming Fields

import Serde from "mo:serde";

    // type JsonSchemaWithReservedKeys = {
    //     type: Text; // reserved
    //     label: Text;  // reserved
    //     id: Nat;
    // };

type Item = {
    item_type: Text;
    item_label: Text;
    id: Nat
};

let jsonText = "{\"type\": \"bar\", \"label\": \"foo\", \"id\": 112}";
let options: Serde.Options = {
    renameKeys = [("type", "item_type"), ("label", "item_label")]
};

let #ok(blob) = Serde.JSON.fromText(jsonText, ?options);
let renamedKeys: ?Item = from_candid(blob);

assert renamedKeys == ?{ item_type = "bar"; item_label = "foo"; id = 112 };

Checkout the usage guide for additional examples:

Limitations

Running Tests

  1. Install dependencies:

  2. Inside the project directory, run:

mops test

Happy coding with serde! 🚀