如何在Crystal语言中创建值为任意类型的Hash?
在Crystal语言中如何表示键为String、值为任意类型的Hash?
我正在处理一个API的表示工作,该API的响应包含一个键为String类型、值可为任意类型的Hash。我查阅了Crystal的类型相关文档,但没找到对应的表示方法。
在OpenAPI规范中,这种结构被称为自由格式对象,定义方式如下:
Free-Form Objects
如果字典的值可以是任意类型(即自由格式对象),使用additionalProperties: true:type: objectadditionalProperties: true
这等价于:type: objectadditionalProperties: {}
在Go语言中,这种类型会被表示为map[string]any或map[string]interface{}。
解答
在Crystal语言中,你可以通过两种方式实现这种结构的表示:
1. Hash(String, JSON::Any)(API场景推荐)
JSON::Any是Crystal标准库专为兼容JSON任意类型设计的类型,支持字符串、数字、布尔值、数组、嵌套哈希等所有JSON允许的类型,完美匹配OpenAPI自由格式对象的需求。同时它内置了类型转换方法,方便后续处理不同类型的值。
示例代码:
# 初始化自由格式哈希 free_form = Hash(String, JSON::Any).new # 添加不同类型的值 free_form["username"] = "john_doe" free_form["score"] = 95 free_form["is_verified"] = true free_form["tags"] = ["crystal", "api"] free_form["profile"] = {"location" => "Beijing", "join_date" => "2024-01-01"} # 访问并转换值类型 username = free_form["username"].as_s score = free_form["score"].as_i tags = free_form["tags"].as_a
如果直接解析API的JSON响应,可直接将结果转为该类型:
api_response = '{"status": "ok", "data": {"id": 123, "details": ["a", "b"]}}' parsed = JSON.parse(api_response).as_h # 直接得到Hash(String, JSON::Any)
2. Hash(String, ::Any)(通用任意类型)
若不需要和JSON序列化绑定,也可以使用Crystal的顶级Any类型,它能容纳所有Crystal对象,但使用时需手动处理类型断言,灵活性稍弱:
generic_hash = Hash(String, ::Any).new generic_hash["count"] = 42 generic_hash["text"] = "hello" # 类型断言访问 count = generic_hash["count"].as(Int32) text = generic_hash["text"].as(String)
内容的提问来源于stack exchange,提问作者Grokify
相关产品推荐
相关产品推荐

