Work with dynamic types
A dynamic type is a wrapper for data whose type is not known until runtime. Dynamic types help when working with data from external sources (like JSON) that support types that do not have an equivalent Flux type.
- Parse JSON into Flux types
- Dynamic type syntax
- Reference values in a dynamic type
- Operate on dynamic types
Dynamic types are not supported in tables
Dynamic types are not supported in Flux tables. To include a dynamic value in a Flux table, you must cast the dynamic type to a Flux basic type. For a full example of casting dynamic types to basic types and including them in a table, see Include dynamic types in a table.
Parse JSON into Flux types
The primary (but not exclusive) use case for dynamic types is converting JSON data into native Flux types; specifically Flux arrays and records.
Because of strict typing rules in Flux, JSON data doesn’t always gracefully parse into native Flux types. The most common reason is that Flux arrays require all children to be the same type. JSON arrays allow elements to be different types.
With Flux records (the corollary of a JSON object), the properties in the record are part of the record’s type. If you have a JSON array of objects where the objects’ schemas are different, the array cannot be parsed as a Flux array because the types of the records in the array do not match.
The dynamic type provides a way to resolve the differences between JSON and Flux types.
Dynamic type syntax
Flux does not provide a literal syntax for dynamic types. To cast a value to a dynamic type:
- Import the
experimental/dynamic
package. - Use
dynamic.dynamic()
to convert a value to a dynamic type.
import "experimental/dynamic"
dynamic.dynamic(v: "Example string")
// Returns dynamic(Example string)
Reference values in a dynamic type
Use bracket and dot notation to reference values in dynamic records and arrays.
Use the exists
operator to check if a dynamic type contains a non-null value.
- Reference values in a dynamic record
- Reference values in a dynamic array
- Ensure a dynamic type contains a non-null value
Reference values in a dynamic record
import "experimental/dynamic"
record = {one: 1, two: 2, three: 3}
dynamicRecord = dynamic.dynamic(v: record)
dynamicRecord.one
// Returns dynamic(1)
dynamicRecord["two"]
// Returns dynamic(2)
Reference values in a dynamic array
import "experimental/dynamic"
arr = ["a", "b", "c"]
dynamicArr = dynamic.asArray(v: dynamic.dynamic(v: arr))
dynamicArr[0]
// Returns dynamic(a)
Ensure a dynamic type contains a non-null value
Use the exists
operator to check if a dynamic type contains a non-null value.
If you attempt to access members of a null dynamic value, Flux returns an error.
exists
lets you guard against errors caused by attempting to access members in
null dynamic values.
Operate on dynamic types
Convert dynamic types to Flux types
Basic types
Use string()
to convert a dynamic type to a string.
string()
returns the string representation of the dynamic value.
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "string")
string(v: dynamicValue)
// Returns "string"
Use int()
to convert a dynamic type to an integer.
int()
returns the integer equivalent
of the dynamic value.
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "12")
int(v: dynamicValue)
// Returns 12
Use uint()
to convert a dynamic type to an unsigned integer (UInteger).
uint()
returns the UInteger equivalent
of the dynamic value.
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "12")
uint(v: dynamicValue)
// Returns 12
Use float()
to convert a dynamic type to a floating point value.
float()
returns the float equivalent
of the dynamic value.
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "12.1")
float(v: dynamicValue)
// Returns 12.1
Use bool()
to convert a dynamic type to a boolean value.
bool()
returns the boolean equivalent
of the dynamic value.
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "true")
bool(v: dynamicValue)
// Returns true
Use duration()
to convert a dynamic type to a duration value.
duration()
returns the duration equivalent
of the dynamic value.
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: 3000000000)
duration(v: dynamicValue)
// Returns 3s
Use time()
to convert a dynamic type to a time value.
time()
returns the time equivalent
of the dynamic value.
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: 1640995200000000000)
time(v: dynamicValue)
// Returns 2022-01-01T00:00:00.000000000Z
Use bytes()
to convert a dynamic type to a byte-encoded string.
bytes()
returns the bytes equivalent
of the dynamic value.
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "Hello world!")
bytes(v: dynamicValue)
// Returns 0x48656c6c6f20776f726c6421
- Use
string()
to convert a dynamic type to a string. - Import the
regexp
package and useregexp.compile()
to convert the string value to a regular expression type.
import "experimental/dynamic"
import "regexp"
dynamicValue = dynamic.dynamic(v: "^[abc][123]{1,}")
stringValue = string(v: dynamicValue)
regexp.compile(v: stringValue)
// Returns /^[abc][123]{1,}/
Composite types
Dynamic composite types will almost always come from working with a byte-encoded JSON string. All the examples below assume this.
To convert a JSON array to a Flux array:
-
Import the following packages:
-
Use
dynamic.jsonParse()
to parse a byte-encoded JSON string into a dynamic type. -
Use
dynamic.asArray()
to convert the dynamic-typed array into an array of dynamic types. -
Use
array.map()
to iterate over each element in the array and explicitly cast dynamic types to basic types.
To convert a JSON object to a Flux record:
- Import the
experimental/dynamic
package - Use
dynamic.jsonParse()
to parse a byte-encoded JSON string into a dynamic type. - Define a new record and cast each property of the dynamic type to a basic type.
JSON object
{"first-name": "John", "last-name": "Doe", "age": 42}
Convert a JSON object to a Flux record
import "experimental/dynamic"
json = jsonBytes // Byte-encoded JSON above
parsed = dynamic.jsonParse(data: json)
newRecord = {
fname: string(v: parsed["first-name"]),
lname: string(v: parsed["last-name"]),
age: int(v: parsed.age)
}
// newRecord returns {age: 42, fname: John, lname: Doe}
Check the type of a value inside of a dynamic type
Use dynamic.isType()
to check
the type of a value inside of a dynamic type.
The following example uses the http/requests
package
and the Fruityvice API to return information about
apples as a JSON object.
import "experimental/dynamic"
response = requests.get(url: "https://www.fruityvice.com/api/fruit/apple")
parsed = dynamic.jsonParse(data: response.body)
dynamic.isType(v: parsed.genus, type: "string")
// Returns true
dynamic.isType(v: parsed.nutritions, type: "array")
// Returns false
dynamic.isType(v: parsed.nutritions, type: "object")
// Returns true
Include dynamic types in a table
Dynamic types are not supported in Flux tables. To include a dynamic value in a Flux table, cast the dynamic type to a Flux basic type.
The following example uses array.from()
to
build and ad hoc table using dynamic types.
Each dynamic type must be cast to a Flux basic type when defining the row record.
import "array"
import "experimental/dynamic"
dynamicString = dynamic.dynamic(v: "one")
dynamicInt = dynamic.dynamic(v: 1)
dynamicFloat = dynamic.dynamic(v: 1.0)
dynamicBool = dynamic.dynamic(v: true)
array.from(
rows: [
{
string: string(v: dynamicString),
int: int(v: dynamicInt),
float: float(v: dynamicFloat),
bool: bool(v: dynamicBool),
},
],
)
Convert a JSON array to a Flux table
-
Import the following packages:
-
Use
dynamic.jsonParse()
to parse the the JSON response body returned fromrequests.get()
into a Flux dynamic type. Define a variable to capture the parsed JSON. The example below uses theparsed
variable. -
Use
dynamic.asArray()
to convert the dynamic type returned bydynamic.jsonParse()
to a dynamic array. Define a variable to capture the dynamic array. The example below uses thefruit
variable. -
Use
array.map()
to do the following:- Iterate over each dynamic record in the dynamic array and flatten nested records. Flux tables do not support nested records (the corollary of a JSON object).
- Explicitly cast dynamic values in each dynamic record to a Flux basic type.
The following example uses the http/requests
package
and the Fruityvice API to return information about
various fruit as JSON and then structure the returned data as a Flux table.
import "array"
import "experimental/dynamic"
import "http/requests"
response = requests.get(url: "https://www.fruityvice.com/api/fruit/all")
parsed = dynamic.jsonParse(data: response.body)
fruit = dynamic.asArray(v: parsed)
fruit_flat =
fruit
|> array.map(
fn: (x) =>
({
name: string(v: x.name),
cals: int(v: x.nutritions.calories),
carbs: float(v: x.nutritions.carbohydrates),
fat: float(v: x.nutritions.fat),
protein: float(v: x.nutritions.protein),
sugar: float(v: x.nutritions.sugar),
}),
)
array.from(rows: fruit_flat)
Encode a dynamic type as JSON
Encode a dynamic record as JSON
- Import the
experimental/dynamic
package. - Use
dynamic.dynamic()
to convert the record to a dynamic type. - Use
dynamic.jsonEncode()
to convert the dynamic record into a byte-encoded JSON string.
import "experimental/dynamic"
dynamicRecord = dynamic.dynamic(v: {one: 1, two: 2, three: 3})
dynamic.jsonEncode(v: dynamicRecord)
// Returns the following byte-encoded JSON string:
// {"one":1,"three":3,"two":2}
Encode a dynamic array of different basic types as JSON
Build a dynamic array where each element is a different basic type. This might be necessary if you’re send JSON data to an API that expects an array of values where each value is a different type. Values in a Flux array must be the same type, so you must build a dynamic array of dynamic types:
- Import the
experimental/dynamic
package. - Use
dynamic.dynamic()
to convert the array to a dynamic type. - Use
dynamic.dynamic()
to convert all values in the array to dynamic types. - Use
dynamic.jsonEncode()
to convert the dynamic array into a byte-encoded JSON string.
import "experimental/dynamic"
arr =
dynamic.dynamic(
v: [
dynamic.dynamic(v: "three"),
dynamic.dynamic(v: 2),
dynamic.dynamic(v: true)
],
)
dynamic.jsonEncode(v: arr)
// Returns the following byte-encoded JSON string:
// ["three", 2, true]
Was this page helpful?
Thank you for your feedback!
Support and feedback
Thank you for being part of our community! We welcome and encourage your feedback and bug reports for Flux and this documentation. To find support, use the following resources:
Customers with an annual or support contract can contact InfluxData Support.