Skip to main content

idl2json

Intermediate
Dev Tools

idl2json is a command-line tool used to translate Candid textual values from stdin into JSON values outputted in stdout.

idl2json can be used in workflows where a tool producing Candid values, such as dfx, needs to provide JSON values to JSON-based tools.

Installation

Once you have downloaded cargo, install idl2json with the cargo install command:

cargo install idl2json_cli

Usage

To use idl2json, you must provide standard input to the command in the form of a textual representation of Candid variables. You cannot pass idl2json binary or hex values.

To demonstrate an example, consider the following 'Hello, world!' actor written in Motoko:

import Debug "mo:base/Debug"

actor HelloWorld {
  public func main() {
    Debug.print("Hello World!")
  }
}

The Candid file for this canister contains the following content:

service : {
  main: () -> () oneway;
}

To call this canister's method main, then convert it into JSON using idl2json, run the following command:

dfx canister call hello_world main | idl2json

You will receive the following output:

2024-05-21 17:38:29.930244 UTC: [Canister bkyz2-fmaaa-aaaaa-qaaaq-cai] Hello World!

idl2json can be especially useful to parse and filter large outputs from a canister, such as information about proposals from the NNS canister. For example, consider the following call to the NNS governance canister:

dfx canister call rrkah-fqaaa-aaaaa-aaaaq-cai get_proposal_info '(129396: nat64)' --ic

This call returns a large output that includes the proposal details for proposal 129296. A portion of this output is shown below:

(
  opt record {
    id = opt record { id = 129_396 : nat64 };
    status = 4 : int32;
    topic = 8 : int32;
    failure_reason = null;
    ballots = vec {};
    proposal_timestamp_seconds = 1_713_543_513 : nat64;
    reward_event_round = 1_080 : nat64;
    deadline_timestamp_seconds = opt (1_713_889_113 : nat64);
    failed_timestamp_seconds = 0 : nat64;
    reject_cost_e8s = 1_000_000_000 : nat64;
    derived_proposal_information = null;
    latest_tally = opt record {
      no = 30_214_275_350_511 : nat64;
      yes = 47_423_327_498_625_483 : nat64;
      total = 47_711_095_943_759_321 : nat64;
      timestamp_seconds = 1_713_886_831 : nat64;
    };
    reward_status = 3 : int32;
    decided_timestamp_seconds = 1_713_779_984 : nat64;
    proposal = opt record {
      url = "";
      title = opt "Upgrade NNS Canister: qoctq-giaaa-aaaaa-aaaea-cai to wasm with hash: c171de6a4e3f7f999829e5ff16d0757f1d0d0bc1730ca24e0fd0f1657f470fad";
      action = opt variant {
        ExecuteNnsFunction = record {
          nns_function = 4 : int32;
...

Then, pass this output to idl2json:

dfx canister call rrkah-fqaaa-aaaaa-aaaaq-cai get_proposal_info '(129396: nat64)' --ic | idl2json

This output will be quite long as well. A portion of it is shown below for you to compare to the textual Candid representation shown above:

[
  {
    "ballots": [],
    "deadline_timestamp_seconds": [
      "1713889113"
    ],
    "decided_timestamp_seconds": "1713779984",
    "derived_proposal_information": null,
    "executed_timestamp_seconds": "1713779984",
    "failed_timestamp_seconds": "0",
    "failure_reason": null,
    "id": [
      {
        "id": "129396"
      }
    ],
    "latest_tally": [
      {
        "no": "30214275350511",
        "timestamp_seconds": "1713886831",
        "total": "47711095943759321",
        "yes": "47423327498625483"
      }
    ],
    "proposal": [
      {
        "action": [
          {
            "ExecuteNnsFunction": {
              "nns_function": 4,
              "payload": [
                68,
                73,
                68,
                76,
                4,
...

You can filter this output to get specific information using a command such as:

dfx canister call rrkah-fqaaa-aaaaa-aaaaq-cai get_proposal_info '(129396: nat64)' --ic | idl2json | jq '.[0] | keys'

This filter will return just the top-level JSON keys:

[
  "ballots",
  "deadline_timestamp_seconds",
  "decided_timestamp_seconds",
  "derived_proposal_information",
  "executed_timestamp_seconds",
  "failed_timestamp_seconds",
  "failure_reason",
  "id",
  "latest_tally",
  "proposal",
  "proposal_timestamp_seconds",
  "proposer",
  "reject_cost_e8s",
  "reward_event_round",
  "reward_status",
  "status",
  "topic"
]

dfx supported JSON output

In dfx versions 0.19.0 and newer, the flag --output json can be used with a dfx canister call command. This removes the need to pipe the output to idl2json. Learn more in the dfx documentation.

Resources