Эликсир - прописные ключи в структурах
Я пытаюсь написать клиент CLI в Elixir для API, чтобы я мог войти в систему API, получить данные, необходимые для моих расчетов, а затем выйти из системы. Я определил структуру Packet.Login, которая должна быть моей внутренней структурой данных, которую я получаю после анализа JSON, который я получаю.
Я использую 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 ответ
Чтобы получить доступ к полю карты, представляющему собой атом, начинающийся с заглавной буквы, вам необходимо либо поместить ключ в кавычки, например: foo."Bar"
или используйте синтаксис скобок, например foo[:Bar]
, 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"}"
Я нигде не смог найти документально подтвержденного, но источник в Elixir упоминает об этом в некоторых местах, а также использует этот синтаксис для доступа к некоторым функциям в :erlang
которые имеют имена, которые не являются действительными идентификаторами в Elixir, например :erlang."=<"
,
Интересный факт: вы можете определить функции в Elixir, которые можно вызывать только с помощью этого синтаксиса цитаты:
iex(1)> defmodule Foo do
...(1)> def unquote(:"!@#")(), do: :ok
...(1)> end
iex(2)> Foo."!@#"()
:ok