Как декодировать GeoJson в ReasonML?
Прокомментируйте, пожалуйста, как декодировать файл GeoJson в ReasonML? Я пытаюсь расшифровать координаты без "широты и долготы поля" в декодере, но я не могу найти никакой информации о том, как анализировать координаты поля в файле JSON.
GeoJson файл
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
131.469670264,
33.3158712032
]
},
"properties": {
"index": 0,
"alias": "海地獄-別府市",
"name": "Umi-Jigoku",
"image_url": "https://s3-media1.fl.yelpcdn.com/bphoto/7T1aXG9Q3CAtEbwqFm3Nlw/o.jpg"
}
JsonDecoder (bs-json) в ReasonML
[@genType]
type properties = {
index: int,
alias: string,
name: string,
image_url: string,
geometry: coordinates,
}
and coordinates = {
latitude: float,
longitude: float,
};
let places = "../json/alljapan.json";
module Decode = {
let coordinates = json =>
Json.Decode.{
latitude: json |> field("latitude", float),
longitude: json |> field("longitude", float),
};
let properties = json =>
Json.Decode.{
index: json |> field("index", int),
alias: json |> field("alias", string),
name: json |> field("name", string),
image_url: json |> field("image_url", string),
geometry: json |> field("geometry", coordinates),
};
};
let line = places |> Json.parseOrRaise |> Decode.line;
2 ответа
Вам, вероятно, следует использовать GeoReason, как предлагает @mlms13, но если вы все еще хотите декодировать его самостоятельно, используя bs-json
вы можете использовать тот факт, что кортежи реализованы как массивы в BuckleScript, и использовать pair
декодер для получения значений, затем map
это к вашему типу записи:
let coordinates = json =>
Json.Decode.(
pair(float, float)
|> map(((latitude, longitude)) => {latitude, longitude})
);
На работе мы написали библиотеку под названием GeoReason с целью предоставления типов Reason, конструкторов, кодировщиков и декодеров (вместе с некоторыми вспомогательными функциями, такими какeq
) для структур данных GeoJSON в соответствии со спецификацией RFC-7946.
Я не пробовал использовать библиотеку с React Native, но полагаю, что она должна работать везде, где вы можете скомпилировать Reason в JS.
Обзор
- GeoJSON моделирует множество отношений "или" (элемент или геометрия, где геометрия - это точка, линия или...), которые легко выразить как варианты причины.
- GeoJSON компактен, предпочитает массивы (как кортежи), которые трудно читать. Для этого мы используем записи Reason.
- Декодируем значения с помощью bs-decode
- "Возможности" идут с дополнительными метаданными (поле "свойства"), которыми может быть любой объект JSON с метаданными... Мы не пытаемся декодировать это за пределами словаря key => json:
Js.Dict.t(Js.Json.t)
Применение
Предполагая, что у вас есть значение JSON типа Js.Json.t
, и вы установили GeoReason, следуя инструкциям в README, вы можете декодировать и использовать свои данные следующим образом:
// this is a `Belt.Result` that is either `Ok` with the GeoJSON data, or
// Error with information describing what went wrong while decoding
let decoded = GeoJSON.decode(myFileData);
switch (decoded) {
| Error(parseError) =>
Decode.ParseError.failureToDebugString(parseError) |> Js.log;
// if the GeoJSON value is a "Feature", it may have the following fields,
// but note that technically all of them are optional according to the spec.
// if you want to decode the dictionary of properties, you can do so here
| Ok(GeoJSON.Feature({id, geometry, properties})) =>
properties
->Belt.Option.flatMap(dict => Js.Dict.get(dict, "image_url"))
->Belt.Option.flatMap(json => Js.Json.decodeString(json))
->Belt.Option.map(url => /* do something with the url? */);
| Ok(Geometry(Point({latlong, altitude})) =>
/* use latitude and longitude? */
| Ok(Geometry(Polygon(data))) => /* ... */
| Ok(_) =>
// lots more cases to handle, like line geometries,
// geometry collections, feature collections, etc...
};
Как вы можете видеть, соответствие на все то, что значение GeoJSON может быть довольно сложный процесс, так это зависит немного от того, что вы надеетесь сделать со значениями. Я добавил в библиотеку несколько помощников, напримерGeoJSON.getPolygons
, который попытается получить список полигонов для любого значения GeoJSON (возвращая пустой список, если полигонов не было). Не стесняйтесь открывать вопросы, если есть дополнительные помощники, которые вам пригодятся.