Skip to content

NPL to JSON mapping

The following sections describe how NPL is mapped to JSON. It follows the same structure as the NPL Type Reference.

Basic Types

Blob

Blob values are represented as a data URL.

type: string
format: byte

Example value:

"data:application/pdf;base64,SGVsbG9Xb3JsZA=="

Boolean

NPL Booleans are represented as JSON booleans.

type: boolean

Example value:

true

DateTime

DateTime values are represented as Strings using the extended date time format with time zones. The OpenAPI specification does not (yet) define a standard format for this, so we provisionally use the zoned-date-time format. This will change once the OpenAPI specification supports the extended date time format.

type: string
format: zoned-date-time

Example value:

"2006-01-02T15:04:05.999+01:00[Europe/Zurich]"

Duration

Duration values are specified as strings with the official duration format.

type: string
format: duration

Example value:

"PT20M34S"

LocalDate

LocalDate values are represented as strings with the official date format.

type: string
format: date

Example value:

"1977-07-24"

Number

Number values are represented as JSON numbers. Note that numbers in JSON are arbitrary precision, but not all clients might interpret this correctly.

type: number

Example value:

3.1415926535897932384626433832795028841971

Period

Period values are represented using the _Period schema, which is automatically defined in the OpenAPI specification when necessary:

_Period:
  required:
    - days
    - months
    - weeks
    - years
  type: object
  properties:
    days:
      type: integer
    weeks:
      type: integer
    months:
      type: integer
    years:
      type: integer

Example value:

{
  "days": 0,
  "weeks": 1,
  "months": 0,
  "years": 17
}

Text

Text values are represented as strings.

type: string

Example value:

"this is a string"

Unit

Unit values are currently not supported.

Protocol actions returning Unit instead return the protocol itself.

Collection types

List

List values are represented as JSON arrays. The list elements are defined recursively.

type: array
items:
# recursively defined

Example schema:

type: array
items:
  $ref: '#/components/schemas/MyStruct'

Example value:

[
  "this",
  "is",
  "a",
  "list",
  "of",
  "text"
]

Map

Map values are represented as JSON arrays of pairs, which themselves are defined by a separate schema (see below).

type: array
items:
  $ref: # reference to the relevant Pair type

The one exception are Map values where the keys are of type Text. These are defined as a JSON dictionary:

type: object
additionalProperties:
# recursively defined based on the type of the values.

Example schema for Map<Number, Text>:

type: array
items:
  $ref: '#/components/schemas/Number_Text_Pair'

Example value for a Map<Number,Text>:

[
  {
    "first": 12,
    "second": "value"
  },
  {
    "first": 19,
    "second": "text"
  }
]

Example schema for Map<Text, Number>:

type: array
items:
  type: number

Example value for a Map<Text,Number>:

{
  "value": 12,
  "text": 19
}

Set

Set values are represented as JSON arrays. The set elements are defined recursively.

type: array
items:
# recursively defined

Example schema for Set<Optional<Text>>:

type: array
items:
  type: string
  nullable: true

Example value:

[
  "this",
  "set",
  "text",
  "of",
  "is"
]

Complex types

Functional

Functional types are not supported.

IndexedElement

IndexedElements are defined as a JSON object using a named schema, where the name is derived from the underlying type.

<T>_IndexedElement:
  type: object
  required:
    - index
    - element
  properties:
    index:
      type: integer
    element:
    # recursively defined

Example schema for an IndexedElement<List<Text>:

LocalDate_IndexedElement:
  type: object
  required:
    - index
    - element
  properties:
    index:
      type: integer
    element:
      type: array
      items:
        type: string

Example value:

{
  "index": 0,
  "element": [
    "another",
    "list",
    "of",
    "text"
  ]
}

NotifyResult

NotifyResult is represented as a JSON object using a named schema, where the name is derived from the underlying types.

Example schema for NotifyResult<Number>:

Number_Notification:
  required:
  - type
  type: object
  properties:
    type:
      type: string
      enum:
      - success
      - failure
    value:
      type: number
NPL Expression Serializes to Deserializes to
NotifySuccess<Number>(10) { "type": "success", "value": 10 } NotifySuccess<Number>(10)
NotifySuccess<Optional<Number>>(Some(10)) { "type": "success", "value": 10 } NotifySuccess<Optional<Number>>(Some(10)
NotifySuccess<Optional<Number>>(None) { "type": "success" } NotifySuccess<Optional<Number>>(None)
NotifyFailure() { "type": "failure" } NotifyFailure

Optional

Optional values are represented by their underlying type, with the additional property nullable. If the underlying type is a named schema, the named schema is referenced using anyOf.

Warning

Nested optionals with a None value are always serialized into a single null value.

NPL Expression Serializes to Deserializes to
optionalOf<Optional<Number>>(None) null None
optionalOf<Optional<Number>>(Some(42)) 42 Optional<Optional<Number>>(Some(42))
# definition of underlying type
nullable: true

Example schema for Optional<Text>:

type: string
nullable: true

Example schema for Optional<MyStruct>

anyOf:
  - $ref: '#/components/schemas/MyStruct'
nullable: true

Example value:

null

Pair

Pairs are represented as a JSON object using a named schema, where the name is derived from the underlying types.

<S>_<T>_Pair:
  type: object
  required:
    - first
    - second
  first:
  # recursively defined
  second:
  # recursively defined

Example schema for Pair<Number, Optional<MyStruct>>:

Number_Optional_MyStruct_Pair:
  type: object
  required:
    - first
    - second
  first:
    type: number
  second:
    anyOf:
      - $ref: '#/components/schemas/MyStruct'
    nullable: true

Example value:

{
  "first": 16,
  "second": null
}

Party

Party is represented as a JSON object using a predefined named schema. Note the underscore in the name.

_Party:
  type: object
  required:
    - entity
    - access
  properties:
    entity:
      type: object
      additionalProperties:
        type: array
        items:
          type: string
    access:
      type: object
      additionalProperties:
        type: array
        items:
          type: string

Example value:

{
  "entity": {
    "iss": [
      "https://example.com"
    ],
    "organization": [
      "Example AG"
    ]
  },
  "access": {
    "preferred_email": [
      "john.doe@example.com"
    ]
  }
}

Test

The test object is not supported.

User-defined types

Enum

Enums are represented as strings, using a named schema.

MyEnum:
  type: string
  enum:
    - # list of all enum values

Example schema:

MyEnum:
  type: string
  enum:
    - MyEnumValue
    - MySecondValue
    - MoreValuesAsNeeded

Example value:

"MyEnumValue"

Identifier

Identifiers are represented as strings with the UUID format, using a named schema.

MyIdentifier:
  type: string
  format: uuid

Example value:

"05de0d73-f51e-4b4a-9947-94120e7f7ba7"

Protocol

Protocols are represented as JSON objects, using multiple named schemas. The main schema has a number of default fields, all prefixed with @, and one field for each non-private property of the protocol.

Next to the main schema, there are schemas for the parties, the states, the allowed actions, and lists of protocols.

P_Parties:
  required:
    - # once for each protocol party
  type: object
  properties:
  # one property of type Party for each protocol party
P_States:
  type: string
  enum:
    - # list of all defined states
P_Actions:
  type: object
  properties:
    # one property for each action that can be called
    type: string
    format: uri
P_List:
  type: object
  required:
    - items
  properties:
    '@prev':
      type: string
      format: uri
    '@next':
      type: string
      format: uri
    items:
      type: array
      items:
      # reference to P
P:
  type: object
  required:
    - @id
    - @parties
    - @actions
    - @state
    # and one for each non-private protocol property
  properties:
    '@id':
      type: string
      format: uuid
    '@parties':
    # reference to P_Parties
    '@state':
    # reference to P_States
    '@actions':
    # reference to P_Actions
    # and one for each non-private protocol property, recursively defined

Example value:

{
  "@id": "05de0d73-f51e-4b4a-9947-94120e7f7bad",
  "@parties": {
    "issuer": {
      "entity": {
        "preferred_email": [
          "john.doe@example.com"
        ]
      },
      "access": {}
    }
  },
  "@actions": {
    "pay": "https://example.com/npl/api/iou/IOU/05de0d73-f51e-4b4a-9947-94120e7f7bad/pay"
  },
  "@state": "unpaid",
  "forAmount": 17.95
}

Protocol Reference

Protocols that are (indirectly) part of another protocol, or protocols that are used as parameters or return types for protocol actions, are represented as the ID of the protocol, using a named schema.

P_Reference:
  type: string
  format: uuid

Example schema:

Iou_Reference:
  type: string
  format: uuid

Example value:

"05de0d73-f51e-4b4a-9947-94120e7f7bad"

Struct

Structs are represented as JSON objects, using a named schema. Each property of the struct is recursively defined.

S:
  type: object
  required:
    - # one for each property of the struct
  properties:
  # one for each property of the struct

Example schema:

MyStruct:
  type: object
  required:
    - name
    - dateOfBirth
    - length
    - preferences
  properties:
    name:
      type: string
    dateOfBirth:
      type: string
      format: date
    length:
      type: number
    preferences:
      anyOf:
        - $ref: '#/components/schemas/MyPreferences'
      nullable: true

Example value:

{
  "name": "John Doe",
  "dateOfBirth": "1977-07-24",
  "length": 1.83,
  "preferences": null
}

Symbol

Symbols are represented as JSON numbers.

type: number

Example value:

19.28

Union

Unions are represented as JSON objects using a named schema, where the name is derived from the underlying types. It contains a separate property type which is used as a discriminator to represent the underlying value.

<S>_<T>_Union:
  type: object
  required:
    - type
    - value
  properties:
    type:
      type: string
      enum:
        - # one for each underlying type
    value:
      oneOf:
        - # recursive definitions for each underlying type

Example schema for Union<Number, MyStruct>:

Number_MyStruct_Union:
  type: object
  required:
    - type
    - value
  properties:
    type:
      type: string
      enum:
        - 'Number'
        - '/example/name/MyStruct'
    value:
      oneOf:
         - type: number
         - $ref: '#/components/schemas/MyStruct'

Example value:

{
  "type": "Number",
  "value": 18
}

Protocol action parameters

Parameters on protocol actions and constructors are represented as JSON objects using a named schema, where the name is derived from the protocol and the action itself. Each action parameter corresponds to a property.

Example schema for the payload of permission pay(amount: Number, description: Optional<Text>):

MyProtocol_Pay_Command:
  type: object
  required:
    - amount
    - description
  fields:
    amount:
      type: number
    description:
      type: string
      nullable: true

Example value:

{
  "amount": 17.20,
  "description": null
}