How to determine Developer Field's value type is a String or String[]?

In my understanding, decoding array of string is like this, if we have this bytes [118,97,108,49,0,118,97,108,50,0], it can be translated to String[ "val1", "val2" ].

Determining Field's value as String or or String[] is easy since we can determine it based on Array column value specified in the Profile.xlsx to have [N] or [3] for example:

leader_activity_id_string string [N] String version of the activity ID of each leader in the segment file. 21 characters long for each ID, express in decimal

However, I would like guidance on distinguishing between a String and String[] in the Developer Field. 

This is the only example that I could find, it comes from Suunto's Developer Field (https://apizone.suunto.com/fit-description), but still even thought it explicitly says the value is a String[], it does not specify the Array field found in the field_description, is there any guidance or best practice regarding this?

Here is the example I mentioned earlier. I look forward to hearing from you.Your insights are appreciated. Thank you.

session.suuntoplus_plugin_owner_id - String[], 1 - 10 strings, 1 - 64 characters each.

FieldDescription -messages:

  • developer_data_index: 0

  • field_definition_number: 2

  • field_name: "suuntoplus_plugin_owner_id"

  • units: null

  • fit_base_type_id: String

  • developer_data_index: 0

  • field_definition_number: 3

  • field_name: "suuntoplus_plugin_external_id"

  • units: null

  • fit_base_type_id: String

Profile.xlsx reference on field_description:

field_description
0 developer_data_index uint8
1 field_definition_number uint8
2 fit_base_type_id fit_base_type
3 field_name string [N]
4 array uint8
5 components string
6 scale uint8
7 offset sint8
8 units string [N]
9 bits string
10 accumulate string
13 fit_base_unit_id fit_base_unit
14 native_mesg_num mesg_num
15 native_field_num uint8
  • Any field, regardless of what is in the Profile, can be an array. This needs to be determined at runtime by looking at the byte count in the message definition and dividing that by the size of the data type. That works for everything except strings. For strings you need to convert the array of bytes to a UTF8 string, and then split the string on the null terminator \0 to know if it is an array or not. This is the same for fields in the Profile and Developer Fields.

    You can see how this is done in the JavaScript SDK

    https://github.com/garmin/fit-javascript-sdk/blob/main/src/stream.js#L177 

    and the Java SDK
    https://github.com/garmin/fit-java-sdk/blob/main/com/garmin/fit/FieldBase.java#L1078 

    The Python, C++, and C# SDKs do the same thing.

  • Let me confirm, so what's the Profile is just like a guidance to follow but not an enforcement? For instance, even thought file_id.product_name is a type a string, it's still "allowed" to be an array of string?

  • In practice the Profile should be what is followed to encode files, so the data that is decoded should also follow the the Profile. But the Profile is not enforced by the binary Protocol. You need to read the data from the file that is defined in the messaged definitions an then apply the Profile. 

  • Ah right, we have two contexts, first is the Profile and the second is the FIT Protocol itself. The decoder and the encoder should have the ability to decode/encode data in FIT Protocol form regardless the Profile, while validating the Profile should be done in another layer. In Profile context, is there any best practices to define Developer Field in the field_description that my string value would be a single value or an array by utilising the array field (maybe can you give me a hint what is that field used for) ? Or we can simplify it: it's up to the manufacturer to decide and we just provide the value as we decode at runtime, same applies for manufacturer specific messages (Product Profile).