https://github.com/javadev/address-search-utility
https://github.com/javadev/address-search-utility
Last synced: 3 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/javadev/address-search-utility
- Owner: javadev
- License: mit
- Created: 2017-04-26T08:06:27.000Z (about 8 years ago)
- Default Branch: main
- Last Pushed: 2024-05-09T13:05:00.000Z (about 1 year ago)
- Last Synced: 2025-01-31T08:32:59.167Z (5 months ago)
- Language: Java
- Size: 14.6 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# address-search-utility
[](https://github.com/javadev/address-search-utility/actions/workflows/maven.yml)
Задача:
Написать программу, которая с консоли считывает адрес (в пределах Петербурга), и выводит список всех мест, которые находятся по этому адресу (кафе, магазины и так далее).Задача разбивается на три этапа:
- Считать адрес.
- Сделать запрос к серверу
- Вывести результат.Первый и третий пункт не сильно нуждаются в пояснении, остановимся на запросе к серверу.
Эту задачу тоже можно разбить на нескольк этапов:
- Генерация запроса
- Запрос к серверу
- Подготовка к обработке ответа
- Обработка ответаРассмотрим это подробнее:
Генерация запроса
Для получения данных по адресу будем использовать OpenStreetMap и Nominatim:
OpenStreetMap (дословно «открытая карта улиц»), сокращённо OSM — некоммерческий веб-картографический проект по созданию силами сообщества участников — пользователей Интернета подробной свободной и бесплатной географической карты мира.
https://ru.wikipedia.org/wiki/OpenStreetMapА Nominatim, это:
Tool to search OSM data by name and address and to generate synthetic addresses of OSM points (reverse geocoding)
http://wiki.openstreetmap.org/wiki/NominatimNominatim предоставляет возможность делать поисковые запросы, без ключей и лицензий. Вот таким, примерно, образом:
nominatim.openstreetmap.org/search?street=Невский+проспект%2C+100&format=json&city=СПбВы можете открыть эту ссылку, и посмотреть на результат вывода.
За «базовую» ссылку можно взять
http://nominatim.openstreetmap.org/search?street=%s&format=json&city=СПбОднако, чтобы запрос прошел удачно, следует убрать из ссылки недопустимые символы, то есть сделать Percent-encoding, он же URL Encoding.
Для этого в java можно воспользоваться статическим методом encode в классе URLEncoder, вот так:
```java
street = URLEncoder.encode(street, "UTF-8");
```Вот и все, URL готов! Осталось теперь сделать запрос к северу…
Запрос к серверу
Тут следует воспользоваться классом URL. Это самое простое. Просто создать, открыть соединение и получить InputStream. Нам его даже не надо читать, за нас это сделает библиотека GSON.
Подготовка к обработке ответа
Ответ к нам приходит в формате JSON. Это важно.
Но нам его не надо парсить вручную, для этого есть библиотека Gson ль компании Google.
О том, как ей пользоваться, будет рассказано на занятии. Но, тем не менее, примеры есть тут:
https://habrahabr.ru/company/naumen/blog/228279/
http://www.javenue.info/post/gson-json-apiНам для подготовки понадобится «обертка» вокруг сущности Place, которую возвращает сервер.
В принципе, хватит и такого:```java
public class Place {
private String display_name, osm_type;
private String type;
}
```Обработка ответа
Тут вроде все просто, но есть нюансы.
Казалось бы, мы могли бы вызвать метод gson.fromJson, передав туда полученные от URL InputStream, но мы знаем, что результат запроса к серверу это не один Place, а несколько.Так как метод fromJson параметризован, то он должен сам внутри создать список наших объектов. Но как уже говорилось, в Java никак нельзя узнать, чем параметризован класс динамически, поэтому бесполезно вызывать метод fromJson передавая туда List. Для решения этой проблемы, GSON использует TypeToken, вот так:
Type listType = new TypeToken>() {}.getType();
Из экземпляра GSON уже вытащит тип и создаст внутри себя лист. Вот так:
```java
List places = gson.fromJson(
new InputStreamReader(inputStreamFromServer), listType);
```Теперь с листом places можно работать, и вывести его на экран.
Если все уже работает
Тогда следует улучшить результат. Хорошо бы, чтобы запрос к серверу выполнялся в другом потоке. Это сделать не сложно. А вот для того, чтобы узнать что поток запрос сделал и распарсил результат, можно «повесить» на него Listener, вроде такого:
```java
interface DownloadListener{
void onError();
void onDownload(List places);
}
```