2017-07-31 68 views
1

我想实现它接受一个通用的有效载荷的一类,然后将其转换成JSON:作为参数的泛型哈希?

require "json" 

class Response 
    alias Payload = Hash(Symbol | String, String | Bool | Int32 | Int64 | Float32 | Float64 | Nil) 
    @payload : Payload 

    def initialize(@payload, @method : String = "sendMessage") 
    end 

    def to_json 
    @payload.merge({"method" => @method}).to_json 
    end 
end 

Response.new({ 
    "chat_id" => update.message.not_nil!.chat.id, 
    "text" => "Crystal is awesome but complicated", 
}) 

,但我得到instance variable '@payload' of Response must be Hash(String | Symbol, Bool | Float32 | Float64 | Int32 | Int64 | String | Nil), not Hash(String, Int64 | String)编译器错误。我该如何克服这一点? Crystal是否支持泛型Hashes?为什么即使类型重叠也无法转换?

Response是分片的一部分,所以我不知道哪些散列会作为参数传递,但Payload必须足够。

+1

我认为你可能在这里错误地使用了哈希。这与Ruby将Hash用作通用的“数据包”非常不同。在Crystal中,您希望创建自定义类或记录类型,而不是在此处使用散列。区别在于,使用Hash时,键和值的类型之间没有关系,这使得该purpouse非常难以使用。如果你创建一个类,每个属性都有它自己的类型,并且可以更容易使用。请不要尝试在Crystal中编程Ruby。 – RX14

+0

@ RX14我明白了。我必须编写比以前用Ruby更多的代码。但它给了我更好的性能和更少的错误:​​) –

+0

是的,它是更多的代码,但从长远来看,这是更少的时间,因为你的错误在编译器中被捕获,而不是在运行时。几个月后,当你回到代码时,很容易知道发生了什么。 – RX14

回答

3

你的有效载荷散列Hash(String, Int32 | String)类型:

typeof({ 
    "chat_id" => update.message.not_nil!.chat.id, 
    "text" => "Crystal is awesome but complicated", 
}) # => Hash(String, Int32 | String) 

但构造函数需要一个Hash(Symbol | String, String | Bool | Int32 | Int64 | Float32 | Float64 | Nil)。 这些是不同类型的,不能神奇铸造。您需要确保您的有效负载具有正确的类型。要做到这一点

一种方式是显式声明的哈希数的类型:

Payload{ 
    "chat_id" => update.message.not_nil!.chat.id, 
    "text" => "Crystal is awesome but complicated", 
} 

这当然不是很大的,但根据您的用例,它可能就足够了。

如果你想有一个允许接收任何类型散列的通用接口,你需要将它转换为Payload类型。这意味着,将数据复制到一个该类型的新的哈希:

def self.new(hash, method : String = "sendMessage") 
    payload = Payload.new 
    hash.each do |key, value| 
    payload[key] = value 
    end 
    new(payload, method) 
end 

对于真实世界的例子,我使用Crinja这种方法了许多不同类型的变化转换为匹配的。

+0

可以使用Payload {“chat_id”=> update.message.not_nil!.chat.id,“text”=>“Crystal很棒但很复杂”}来缩短哈希文字。 – RX14

+0

我总是忘记这个散列字符语法...:D更新了原来的答案。 –

+0

谢谢你的详细解答@JohannesMüller –