сопоставление с вложенными атрибутами ответа JSON - PullRequest
0 голосов
/ 07 сентября 2018

Я пытаюсь найти более элегантный способ установки переменных после получения ответа от функции get_public_request.Я ссылаюсь на var1 и var2 в следующем примере кода:

def get_prices(item) do
    url = item_path(item)
    response = get_public_request(url)
    var1 = response["item"]["buy"]
    var2 = response["item"]["sell"]
end

def get_public_request(url) do
    HTTPoison.start
    case HTTPoison.get(url) do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        Poison.decode!(body)
    ...
    end
end

Ответ, который я получаю (после Poison.decocode), выглядит следующим образом:

%{"at" => 1536333060, "item" => %{"buy" => "8971.71", "area" => "A16", "sell" => "9019.89"}}

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Как и @mudasobwa, я бы делал извлечение данных в get_public_request, но с одним из этих двух других синтаксисов:

сопоставление с образцом на карте

def get_prices(item), do:
    %{"buy":var1, "sell": var2} = item_path(item) |> get_public_request do 

def get_public_request(url) do
    HTTPoison.start
    case HTTPoison.get(url) do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        Poison.decode!(body)["item"] |> Map.take(["buy", "sell"])
    ...
    end
end

Примечание: это решение будет аварийно завершено во время сопоставления с образцом, если отсутствует одно из двух полей «купить» или «продать». вы можете избежать этого, используя case.

сопоставление с образцом на кортеже

def get_prices(item), do: {var1, var2} = item_path(item) |> get_public_request
def get_public_request(url) do
    HTTPoison.start
    case HTTPoison.get(url) do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        Poison.decode!(body)["item"] |> (&({&1["buy"],&1["sell"]}).()
    ...
    end
end

если вы хотите обработать случай, когда в поле есть данные или нет, вы можете добавить следующую проверку:

Poison.decode!(body)["item"] |> (&({Map.has_key?(&1,"buy") && &1["buy"] || nil, Map.has_key?(&1,"sell") && &1["sell"] || nil}).()
0 голосов
/ 07 сентября 2018

В коде, который вы указали, все, что вам нужно в get_prices, - это эти два параметра. Можно было бы явно вернуть их из get_public_request:

def get_public_request(url) do
  HTTPoison.start
  case HTTPoison.get(url) do
    {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
      with %{"item" => %{"buy" => buy, "sell" => sell}} <- Poison.decode!(body),
        do: {buy, sell}
    ...
    end
end

Kernel.SpecialForms.with/1 вернет любое несоответствующее RHO как есть, следовательно, если мы попадем внутрь do, у нас будет то, что нам нужно. Назовите это как:

def get_prices(item) do
  url = item_path(item)
  {var1, var2} = get_public_request(url)
end

Если вы ожидаете, что они не всегда присутствуют в ответе, используйте Kernel.SpecialForms.case/2:

def get_public_request(url) do
  HTTPoison.start
  case HTTPoison.get(url) do
    {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
      case Poison.decode!(body) do
        %{"item" => %{"buy" => buy, "sell" => sell}} -> {buy, sell}
        %{"item" => %{"buy" => buy}} -> {buy, nil}
        %{"item" => %{"sell" => sell}} -> {nil, sell}
        _ -> {nil, nil}
      end
    ...
    end
end
...