Bru Markup Language

Bru is a simple markup language with JSON-like semantics.

It's currently used in Bruno to save details of an API request in a file.

http: {
  method: GET
  url: www.usebruno.com/hello
  headers: {
    Content-Type: application/json
  }
  body: {
    type: xml
    data: '''
      <xml>
        <name>Bru</name>
      </xml>
    '''
  }
}

Why

The Bru syntax naturally evolved from our need to represent API requests in a human readable format in Bruno . There were two key reasons we could not to use the big three - JSON, YAML and TOML:
  • The need for multimaps to represent duplicate keys
  • The need for annotations to ascribe additional information about a key-value pair

Design Goals

Data Types

Primitive Types

There are 4 primitive types in Bru:

  • String
  • Number
  • Boolean
  • Null

The string type can be unquoted if it doesn't contain any special characters.

Composite Types

There are 3 composite types in Bru:

  • Multimap
  • Array
  • Multistring

Multimap

A Multimap is a dictionary (key-value pair) thet can have duplicate keys, enclosed in curly braces. Keys and Values are separated by a colon : and key-value pairs are separated by a newline. Values may be primitive or composite types.
http: {
  query: {
    userId: 1
    userId: 2
  }
}

Arrays

An Array is a list of values separated by a newline, enclosed in square brackets.
meta: {
  name: Get Users
  seq: 1
  tags: [
    sanity
    regression
  ]
}

Multistring

A Multistring is a string that spans multiple lines, enclosed in triple single/double quotes. The content begins on the line after the opening quotes and ends on the line before the closing quotes.
http: {
  body: {
    type: text
    data: '''
      This is a multiline string.
      It can span multiple lines.
    '''
  }
}

Annotations

Annotations are used to ascribe additional information about a key-value pair. An annotation starts with @ and ends with a newline. Arguments may be passed to an annotation in parentheses and separated by commas. Only primitive types can be passed as arguments.
http: {
  method: 'GET'
  url: 'https://www.usebruno.com/hello'
  headers: {
    Content-Type: 'application/json'

    @disabled
    @description('This is a sample request')
    Authorization: 'Bearer{{token}}'
  }
  param: {
    query: {
      @description('The status of the user')
      @enum('active', 'inactive')
      status: 'active'
    }
  }
}

Comments

Comments start with pound/hash - # and end with a newline. Inline comments are not supported.
# This is a comment

http: {
  # This is a comment, too
}