2017-04-12 32 views
0

我正在嘗試在API中編寫一個CLI客戶端,以便我可以登錄API系統,獲取我需要的數據,然後註銷。我已經定義了一個Packet.Login結構,該結構應該是我的內部數據結構,在解析我接收到的JSON後,我將結束這個結構。Elixir - 結構中的大寫字母鍵

我正在使用Poison來解析JSON。問題在於,由於API返回大寫屬性,因此在打印或解析時我無法匹配它們,因爲毒藥將返回帶有這些大寫鍵的映射。問題是,我似乎不可能像這樣使用別名。如果我嘗試使用另一種語法,

packet[:Token] 

它仍然不起作用,而是給我一個錯誤。但是這次關於Packet.Login沒有實現Access行爲。我可以理解這一部分,但不是第一個問題。我試圖讓代碼很簡單。

defmodule Packet.Login do 
    defstruct [:Data, :Token] 
end 

defimpl String.Chars, for: Packet.Login do 
    def to_string(packet) do 
    "Packet:\n---Token:\t\t#{packet.Token}\n---Data:\t#{packet.Data}" 
    end 
end 

loginPacket = Poison.decode!(json, as: %Packet.Login{}) 
IO.puts "#{loginPacket}" 

當試圖編譯上面我得到這個:

** (CompileError) lib/packet.ex:31: invalid alias: "packet.Token". If you wanted to define an alias, an alias must expand to an atom at compile time but it did not, you may use Module.concat/2 to build it at runtime. If instead you wanted to invoke a function or access a field, wrap the function or field name in double quotes 
(elixir) expanding macro: Kernel.to_string/1 

有沒有辦法,我以某種方式解決這一問題?我曾想過解析地圖並首先將所有字段去掉大寫,但我寧願不要。

爲什麼我不能有一個結構的大寫鍵?但似乎我可以,只要我不嘗試使用它們。

+1

嘗試'包「令牌」'和'包「數據」'。 。 – Dogbert

+0

哇。是的,這工作。那麼,關鍵字是一個字符串呢?我想解釋爲什麼這是必要的。 – Simon

+0

@Dogbert作出並回答解釋爲什麼我可以接受答案(鑑於解釋足夠的解釋):) – Simon

回答

2

爲了訪問以大寫字母開頭的原子映射的字段,需要將該鍵放在引號中,例如, foo."Bar"或使用括號語法,例如foo[:Bar]。 Elixir中的foo.Bar被解析爲別名。使用結構體時,不能使用括號語法,因此最簡單的方法是在字段名稱周圍使用引號。在代碼中,你會因此需要改變:

"Packet:\n---Token:\t\t#{packet.Token}\n---Data:\t#{packet.Data}" 

到:

"Packet:\n---Token:\t\t#{packet."Token"}\n---Data:\t#{packet."Data"}" 

我找不到這個文件明確任何地方,但藥劑的來源說起這in some places並且還使用這個語法來訪問某些功能:erlang中的名稱不是Elixir中的有效標識符,例如:erlang."=<"


有趣的事實:你可以在花好月圓定義函數只能用這句話語法也被稱爲:

iex(1)> defmodule Foo do 
...(1)> def unquote(:"[email protected]#")(), do: :ok 
...(1)> end 
iex(2)> Foo."[email protected]#"() 
:ok 
+0

這個有趣的事實雖然很奇怪,哈哈哈。感謝您提供最快捷的答案。我想你在半分鐘內回答了(評論),它爲我省了很多麻煩,試圖找到它。正如你所說,我沒有在任何地方找到這種記錄。 – Simon

+1

:)我很早以前在閱讀kernel.ex時看到對「:erlang。」<=「'的調用時,我想我學會了這種語法。 – Dogbert