MAINNET:
HEALTHY
TESTNET:
HEALTHY
/
onflow.org
Flow Playground

JSON-Cadence Data Interchange Format


Version 0.2.0

JSON-Cadence is a data interchange format used to represent Cadence values as language-independent JSON objects.

This format includes less type information than a complete ABI, and instead promotes the following tenets:

  • Human-readability - JSON-Cadence is easy to read and comprehend, which speeds up development and debugging.
  • Compatibility - JSON is a common format with built-in support in most high-level programming languages, making it easy to parse on a variety of platforms.
  • Portability - JSON-Cadence is self-describing and thus can be transported and decoded without accompanying type definitions (i.e. an ABI).

Void

{
  "type": "Void"
}

Example

{
  "type": "Void"
}

Optional

{
  "type": "Optional",
  "value": null | <value>
}

Example

// Non-nil

{
  "type": "Optional",
  "value": {
    "type": "UInt8",
    "value": "123"
  }
}

// Nil

{
  "type": "Optional",
  "value": null
}

Bool

{
  "type": "Bool",
  "value": true | false
}

Example

{
  "type": "Bool",
  "value": true
}

String

{
  "type": "String",
  "value": "..."
}

Example

{
  "type": "String",
  "value": "Hello, world!"
}

Address

{
  "type": "Address",
  "value": "0x0" // as hex-encoded string with 0x prefix
}

Example

{
  "type": "Address",
  "value": "0x1234"
}

Integers

[U]Int, [U]Int8, [U]Int16, [U]Int32,[U]Int64,[U]Int128, [U]Int256, Word8, Word16, Word32, or Word64

Although JSON supports integer literals up to 64 bits, all integer types are encoded as strings for consistency.

While the static type is not strictly required for decoding, it is provided to inform client of potential range.

{
  "type": "<type>",
  "value": "<decimal string representation of integer>"
}

Example

{
  "type": "UInt8",
  "value": "123"
}

Fixed Point Numbers

[U]Fix64

Although fixed point numbers are implemented as integers, JSON-Cadence uses a decimal string representation for readability.

The format is exactly "<integer>.<fractional>" and not just "<integer>".

This is a safety measure: As fixed-point numbers are implemented as integers, an implementation might pass in the integer value and thus accidentally pass a much larger value then intended.

For example, the UFix64 value 1.0 is represented by the integer 100000000 (as UFix64 has a scale of 8). An implementation might accidentally pass "100000000" assuming it means the same as "1.0", and then a decoder would instead interpret it as "100000000.0".

{
    "type": "[U]Fix64",
    "value": "<integer>.<fractional>"
}

Example

{
    "type": "Fix64",
    "value": "12.3"
}

Array

{
  "type": "Array",
  "value": [
    <value at index 0>,
    <value at index 1>
    // ...
  ]
}

Example

{
  "type": "Array",
  "value": [
    {
      "type": "Int16",
      "value": "123"
    },
    {
      "type": "String",
      "value": "test"
    },
    {
      "type": "Bool",
      "value": true
    }
  ]
}

Dictionary

Dictionaries are encoded as a list of key-value pairs to preserve the deterministic ordering implemented by Cadence.

{
  "type": "Dictionary",
  "value": [
    {
      "key": "<key>",
      "value": <value>
    },
    ...
  ]
}

Example

{
  "type": "Dictionary",
  "value": [
    {
      "key": {
        "type": "UInt8",
        "value": "123"
      },
      "value": {
        "type": "String",
        "value": "test"
      },
    }
  ],
  // ...
}

Composites (Struct, Resource, Event, Contract, Enum)

Composite fields are encoded as a list of name-value pairs in the order in which they appear in the composite type declaration.

{
  "type": "Struct" | "Resource" | "Event" | "Contract" | "Enum",
  "value": {
    "id": "<fully qualified type identifier>",
    "fields": [
      {
        "name": "<field name>",
        "value": <field value>
      },
      // ...
    ]
  }
}

Example

{
  "type": "Resource",
  "value": {
    "id": "0x3.GreatContract.GreatNFT",
    "fields": [
      {
        "name": "power",
        "value": {"type": "Int", "value": "1"}
      }
    ]
  }
}

Path

{
  "type": "Path",
  "value": {
    "domain": "storage" | "private" | "public",
    "identifier": "..."
  }
}

Example

{
  "type": "Path",
  "value": {
    "domain": "storage",
    "identifier": "flowTokenVault"
  }
}

Type

{
  "type": "Type",
  "value": {
    "staticType": "..."
  }
}

Example

{
  "type": "Type",
  "value": {
    "staticType": "Int"
  }
}

Capability

{
  "type": "Capability",
  "value": {
    "path": <path>,
    "address": "0x0",  // as hex-encoded string with 0x prefix
    "borrowType": "<type ID>",
  }
}

Example

{
  "type": "Capability",
  "value": {
    "path": "/public/someInteger",
    "address": "0x1",
    "borrowType": "Int",
  }
}
Edit on GitHub