搜索后,如何使用HTTParty gem从API返回特定的json键/值?

时间:2019-04-24 15:06:28

标签: ruby-on-rails ruby geocoding rails-api httparty

目前,我有一个简单的应用程序,该应用程序使用外部API并允许用户查询并返回json。它返回所有键/值,但我只希望它在json中返回latlon,或者至少我只想在我的视图中显示这两个。这是我的代码:

locationiq_api.rb

class LocationiqApi
  include HTTParty

  BASE_URI = "https://eu1.locationiq.com/v1/search.php"

  attr_accessor :city

  def initialize(api_key, format = "json")
    @options = { key: api_key, format: format }
  end

  def find_coordinates(city)
    self.class.get(BASE_URI, query: @options.merge({ q: city }))
  end

  def handle_error
    if find_coordinates.code.to_i = 200
      find_coordinates.parsed_response
    else
      raise "Couldn't connect to LocationIQ Api"
    end
  end
end 

locations_controller.rb

class LocationsController < ApplicationController

  def index
    @search = LocationiqApi.new("pk.29313e52bff0240b650bb0573332121e").find_coordinates(params[:q])
  end
end

locations.html.erb

<main>
  <h1>Location Search</h1>
  <!-- Button to search find coordinates -->
  <%= form_tag(locations_path, method: :get) do %>
    <%= label_tag(:q, "Search: ") %>
    <%= text_field_tag(:q) %>
    <%= submit_tag("Find coordinates") %>
  <% end %><br>

  <h2>Search results:</h2>

</main>

<%= @search %>

返回的json:

[{"place_id":"100066","licence":"https:\/\/locationiq.com\/attribution","osm_type":"node","osm_id":"107775","boundingbox":["51.3473219","51.6673219","-0.2876474","0.0323526"],"lat":"51.5073219","lon":"-0.1276474","display_name":"London, Greater London, England, SW1A 2DX, United Kingdom","class":"place","type":"city","importance":0.9654895765402,"icon":"https:\/\/locationiq.org\/static\/images\/mapicons\/poi_place_city.p.20.png"}]

2 个答案:

答案 0 :(得分:1)

假设您有一个类似于以下示例的JSON字符串:

"[{\"place_id\":\"100066\",\"lat\":\"51.5073219\",\"lon\":\"-0.1276474\",\"class\":\"place\",\"type\":\"city\"}]"

那么您应该能够做到(大致而言):

JSON.dump(
  JSON.
    parse(
      "[{\"place_id\":\"100066\",\"lat\":\"51.5073219\",\"lon\":\"-0.1276474\",\"class\":\"place\",\"type\":\"city\"}]"
    ).
    first.
    slice('lat', 'lon')
)

这应该给您:

 => "{\"lat\":\"51.5073219\",\"lon\":\"-0.1276474\"}" 

现在,我记得HTTParty可能已经将API响应转换为Ruby对象(数组或哈希),因此可能不需要JSON.dump。而且,您可能还想做其他小提琴(例如,如果您更喜欢将符号用作键而不是字符串,则可以使用with_indifferent_access

请明确一点,如果您希望将其作为类方法的一部分,则可以执行以下操作:

class LocationiqApi
  include HTTParty

  BASE_URI = "https://eu1.locationiq.com/v1/search.php"

  attr_accessor :city

  def initialize(api_key, format = "json")
    @options = { key: api_key, format: format }
  end

  def find_coordinates(city)
    JSON.dump(
      JSON.
        parse(
          self.class.get(BASE_URI, query: @options.merge({ q: city }))
        ).
        first.
        slice('lat', 'lon')
    )
  end

  def handle_error
    if find_coordinates.code.to_i = 200
      find_coordinates.parsed_response
    else
      raise "Couldn't connect to LocationIQ Api"
    end
  end
end

如果self.class.get(BASE_URI, query: @options.merge({ q: city }))返回的有效字符串JSON代表array的{​​{1}}以外的任何其他字符串,则可能会失败。

我想关键是:

  • 您需要将JSON转换(解析)为Ruby可以使用的东西;
  • 解析后,您需要从hashes个哈希中获取一个hash(假设哈希数组始终是解析结果);
  • 您可以使用array仅使用所需的那些键值对;
  • 然后,由于您已规定要返回JSON,因此您需要使用slice将Ruby对象转换回JSON。我想,您也可以使用JSON.dump。漂浮在船上的人。

答案 1 :(得分:-1)

尝试一下:

@search.map {|r| {lat: r['lat'], lon: r['lon']} }

将是哈希数组