与动态类型一起工作
A 动态 类型是一个数据的包装器,其类型在运行时才会被确定。动态类型在处理来自外部来源(如 JSON)的数据时很有帮助,这些数据支持没有等效 Flux 类型的类型。
不支持动态类型在表中
Flux 表中不支持动态类型。 要在 Flux 表中包含动态值,您必须 将动态类型转换为 Flux 基本类型。 有关将动态类型转换为基本类型并将其包含在表中的完整示例,请参见 在表中包含动态类型。
将 JSON 解析为 Flux 类型
动态类型的主要(但不是唯一)用例是将 JSON 数据转换为原生的 Flux 类型;具体来说是 Flux arrays 和 records。
由于Flux中严格的类型规则,JSON数据并不总是能够优雅地解析为本机Flux类型。最常见的原因是Flux数组要求所有子元素应为相同类型,而JSON数组允许元素具有不同类型。
使用 Flux 记录(JSON 对象的对应物),记录中的属性是记录类型的一部分。 如果您有一个对象的 JSON 数组,其中对象的模式不同, 则该数组无法被解析为 Flux 数组,因为数组中记录的类型不匹配。
动态类型提供了一种解决JSON和Flux类型之间差异的方法。
动态类型语法
Flux不提供动态类型的字面语法。 要将一个值转换为动态类型:
- 导入
experimental/dynamic包。 - 使用
dynamic.dynamic()将一个值转换为动态类型。
import "experimental/dynamic"
dynamic.dynamic(v: "Example string")
// Returns dynamic(Example string)
动态类型中的参考值
使用括号和点符号来引用动态记录和数组中的值。
使用 exists 操作符来检查动态类型是否包含非空值。
动态记录中的参考值
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)
动态数组中的参考值
import "experimental/dynamic"
arr = ["a", "b", "c"]
dynamicArr = dynamic.asArray(v: dynamic.dynamic(v: arr))
dynamicArr[0]
// Returns dynamic(a)
确保动态类型包含非空值
使用 exists 操作符检查动态类型是否包含非空值。 如果您尝试访问空动态值的成员,Flux 将返回错误。 exists 让您可以防止因尝试访问空动态值中的成员而导致的错误。
对动态类型进行操作
将动态类型转换为Flux类型
基本类型
使用 string() 将动态类型转换为字符串。string() 返回动态值的字符串表示形式。
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "string")
string(v: dynamicValue)
// Returns "string"
使用 int() 将动态类型转换为整数。
int() 返回动态值的 整数等价。
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "12")
int(v: dynamicValue)
// Returns 12
使用 uint() 将动态类型转换为无符号整数(UInteger)。uint() 返回动态值的 UInteger 等效。
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "12")
uint(v: dynamicValue)
// Returns 12
使用 float() 将动态类型转换为浮点值。
float() 返回动态值的 浮点等价。
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "12.1")
float(v: dynamicValue)
// Returns 12.1
使用 bool() 将动态类型转换为布尔值。
bool() 返回动态值的 布尔等价。
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "true")
bool(v: dynamicValue)
// Returns true
使用 duration() 将动态类型转换为持续时间值。duration() 返回动态值的 持续时间等值。
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: 3000000000)
duration(v: dynamicValue)
// Returns 3s
使用 time() 将动态类型转换为时间值。time() 返回动态值的 时间等价物。
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: 1640995200000000000)
time(v: dynamicValue)
// Returns 2022-01-01T00:00:00.000000000Z
使用 bytes() 将动态类型转换为字节编码字符串。bytes() 返回动态值的 字节等价。
import "experimental/dynamic"
dynamicValue = dynamic.dynamic(v: "Hello world!")
bytes(v: dynamicValue)
// Returns 0x48656c6c6f20776f726c6421
- 使用
string()将动态类型转换为字符串。 - 导入
regexp包并使用regexp.compile()将字符串 值转换为正则表达式类型。
import "experimental/dynamic"
import "regexp"
dynamicValue = dynamic.dynamic(v: "^[abc][123]{1,}")
stringValue = string(v: dynamicValue)
regexp.compile(v: stringValue)
// Returns /^[abc][123]{1,}/
复合类型
动态复合类型几乎总是来自于处理字节编码的 JSON 字符串。下面的所有示例都假设这一点。
将JSON数组转换为Flux数组:
导入以下包:
使用
dynamic.jsonParse()将字节编码的 JSON 字符串解析为动态类型。使用
dynamic.asArray()将动态类型的数组转换为动态类型的数组。使用
array.map()来迭代数组中的每个元素 并显式地 转换动态类型为基本类型。
将JSON对象转换为Flux记录:
- 导入
experimental/dynamic包 - 使用
dynamic.jsonParse()将字节编码的 JSON 字符串解析为动态类型。 - 定义一个新记录并 将动态类型的每个属性转换为基本类型。
JSON对象
{"first-name": "John", "last-name": "Doe", "age": 42}
将 JSON 对象转换为 Flux 记录
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}
检查动态类型中值的类型
使用 dynamic.isType() 来检查动态类型中值的类型。
以下示例使用了 http/requests 包 和 Fruityvice API 来返回关于苹果的信息,格式为 JSON 对象。
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
在表中包含动态类型
Flux 表中不支持动态类型。 要在 Flux 表中包含动态值, 将动态类型转换为 Flux 基本类型。
以下示例使用 array.from() 来构建一个临时表,使用动态类型。每个动态类型在定义行记录时必须转换为 Flux 基本类型。
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),
},
],
)
将 JSON 数组转换为 Flux 表
导入以下包:
使用
dynamic.jsonParse()来解析从requests.get()返回的 JSON 响应体为 Flux 动态类型。定义一个变量来捕获解析后的 JSON。下面的示例使用parsed变量。使用
dynamic.asArray()将dynamic.jsonParse()返回的动态类型转换为动态 数组。定义一个变量来捕获动态数组。 下面的示例使用fruit变量。使用
array.map()来完成以下操作:- 遍历动态数组中的每个动态记录,并扁平化嵌套记录。 Flux 表格不支持嵌套 记录 (这与 JSON 对象相对应)。
- 明确地将每个动态记录中的动态值转换为 Flux 基本类型。
下面的例子使用了http/requests 包和Fruityvice API来返回关于各种水果的信息,格式为JSON,然后将返回的数据构造成一个Flux表。
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)
将动态类型编码为JSON
将动态记录编码为JSON
- 导入
experimental/dynamic包。 - 使用
dynamic.dynamic()将记录转换为动态类型。 - 使用
dynamic.jsonEncode()将动态记录转换为字节编码的 JSON 字符串。
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}
将不同基础类型的动态数组编码为JSON
构建一个动态数组,其中每个元素都是不同的基本类型。 如果您要向一个期望值数组的API发送JSON数据,而每个值都是不同类型的,这可能是必要的。 Flux数组中的值必须是相同的类型,因此您必须构建一个动态类型的动态数组:
- 导入
experimental/dynamic包。 - 使用
dynamic.dynamic()
将数组转换为动态类型。 - 使用
dynamic.dynamic()将数组中的所有值转换为动态类型。 - 使用
dynamic.jsonEncode()将动态数组转换为字节编码的 JSON 字符串。
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]