Go: Marshal Method for FTL Messages

The FTL API implements the marshal and unmarshal interfaces of the Go language. This topic specifies datatype conversions.

Methods

The type Message type has two methods to conveniently import and export message fields:
  • Marshal imports a Go structure or map into an FTL message.
  • Unmarshal exports the fields of an FTL message to a Go structure or map.

FTL marshaling and unmarshaling support only those maps with key type string.

Marshaling ignores nil as the field value of a Go structure and as a slice element.

FTL Numeric Field Types

FTL messages store all Go language integral types as TIB_FIELD_TYPE_LONG fields, corresponding to the Go language type int64.

FTL messages store all Go language floating-poinjt types as TIB_FIELD_TYPE_DOUBLE fields, corresponding to the Go language type float64.

These designations apply within the following tables.
  • IT refers to any of the following integral types: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, bool.
  • FT refers to any of the following floating-point types: float32, float64.
Conversion of Go Types to FTL Fields
Go Type Marshals to FTL Message Field Type
IT

*IT

TIB_FIELD_TYPE_LONG
FT

*FT

TIB_FIELD_TYPE_DOUBLE
[]IT

*[]IT

[]*IT

*[]*IT

TIB_FIELD_TYPE_LONG_ARRAY
[]FT

*[]FT

[]*FT

*[]*FT

TIB_FIELD_TYPE_DOUBLE_ARRAY
string

*string

TIB_FIELD_TYPE_STRING
[]string

*[]string

[]*string

*[]*string

TIB_FIELD_TYPE_STRING_ARRAY
byte
*byte
Note: []*byte and *[]*byte are not allowed.
TIB_FIELD_TYPE_OPAQUE
time.Time

*time.Time

TIB_FIELD_TYPE_DATETIME
[]time.Time

*[]time.Time

[]*time.Time

*[]*time.Time

TIB_FIELD_TYPE_DATETIME_ARRAY
structure

pointer to structure

TIB_FIELD_TYPE_MESSAGE
embedded structure

pointer to embedded structure

individual fields within the message
ftl.Message

*ftl.Message

TIB_FIELD_TYPE_MESSAGE
[]ftl.Message

*[]ftl.Message

[]*ftl.Message

*[]*ftl.Message

TIB_FIELD_TYPE_MESSAGE_ARRAY
ftl.Inbox

*ftl.Inbox

TIB_FIELD_TYPE_INBOX
map[string] TIB_FIELD_TYPE_MESSAGE
Note: Each element of the map marshals into a field within the message, with the element key becoming the field name. The key type must be string.
Conversion of FTL Fields to Go Types
FTL Message Field Type Unmarshals to Go Type
TIB_FIELD_TYPE_LONG

Supports strict conversion.

IT

*IT

TIB_FIELD_TYPE_DOUBLE

Supports strict conversion.

FT

*FT

TIB_FIELD_TYPE_LONG_ARRAY []IT

*[]IT

[]*IT

*[]*IT

The target struct must be a slice, not an array.

TIB_FIELD_TYPE_DOUBLE_ARRAY []FT

*[]FT

[]*FT

*[]*FT

The target struct must be a slice, not an array.

TIB_FIELD_TYPE_STRING string

*string

TIB_FIELD_TYPE_STRING_ARRAY []string

*[]string

[]*string

*[]*string

The target struct must be a slice, not an array.

TIB_FIELD_TYPE_OPAQUE byte

*byte

TIB_FIELD_TYPE_DATETIME time.Time

*time.Time

TIB_FIELD_TYPE_DATETIME_ARRAY []time.Time

*[]time.Time

[]*time.Time

*[]*time.Time

The target struct must be a slice, not an array.

TIB_FIELD_TYPE_MESSAGE structure

embedded structure

ftl.Message

*ftl.Message

map[string]

*map[string]

TIB_FIELD_TYPE_MESSAGE_ARRAY Array of structures

[]ftl.Message

*[]ftl.Message

[]*ftl.Message

*[]*ftl.Message

[]map[string]

*[]map[string]

The target struct must be a slice, not an array.

TIB_FIELD_TYPE_INBOX ftl.Inbox

*ftl.Inbox

Field Tags in struct Definitions

For convenience, you can use field tags to guide marshaling and unmarshaling (similar to JSON processing). For example:

type myStructType struct {
    myFieldA   int `json:"my_field_A" ftl:"myFieldA"`
    myFieldB   int `json:"my_field_B" ftl:"myFieldB,strict"`
    myFieldC   int `json:"my_field_C" ftl:"myFieldC,zeromissing,omitzero"`
}
FTL software recognizes tags with this general form:
ftl:"fieldname[,options]"
  • fieldname is the name of a field in an FTL message, corresponding to the tagged field of the Go struct definition.
  • options is a comma-separated list of options to apply marshaling and unmarshaling the field (see the following table).
  • Separate the individual tags with a space character. Each line of the example illustrates this with a space between the JSON tag and FTL tag.
Option Description
strict When unmarshaling, enforce strict conversion for numeric fields.

In strict conversion, the sign of a numeric FTL field value must be compatible with the corresponding Go language field type. If it is not compatible, the unmarshal call returns an error.

For example, consider the effect of unmarshaling an FTL message field with type TIB_FIELD_TYPE_LONG. The value 100 fits into any unsigned Go field, or into an int8. But the value -1000 does not fit, and strict conversion would reject it.

Non-strict conversion could yield unpredictable values for values that do not fit.

zeromissing When unmarshaling, supply zero values for missing fields.

If the target Go struct definition specifies a field but a corresponding field does not exist in the source FTL message, then conversion sets the Go field to the zero value of its field type.

When this option is absent, unmarshaling does not modify the target Go field unless the field is present in the FTL message.

omitzero When marshaling, omit fields that contain the zero value.

This option is analogous to omitempty in JSON marshaling. If the Go field contains the zero value for its type, then marshaling does not add a corresponding field to the FTL message.

Zero values include false, 0, 0.0, "", a nil pointer or interface value, and any empty array, slice, map, structure, or string.

When this option is absent, marshaling adds an FTL field corresponding to every Go field.

format=format_name Marshal a Go field value that is itself a nested structure to an FTL message with format format_name. (Use this option when your FTL application definition manages all formats.)

When this option is absent, marshal a nested structure to an FTL message of unnamed dynamic format (that is, null format name).