2017-04-12 8 views
0

私はAPIシステムにログインし、計算に必要なデータをフェッチしてからログアウトできるように、API用のElixirにCLIクライアントを書き込もうとしています。私は私が受信したJSONを解析した後に終わる私の内部データ構造であると思われるPacket.Login構造体を定義しました。Elixir - 構造体のキーの大文字化

私はPoisonを使用してJSONを解析しています。問題は、大文字のプロパティを返すAPIのために、Poisonがこれらの大文字のキーを持つマップを返すため、印刷または解析するときに一致させることができないように見えるということです。問題は、このようなエイリアスを使用することが不可能に思えることです。

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