请评论如何在ReasonML中解码GeoJson文件?我尝试在解码器中解码没有"字段纬度和经度"的坐标,但我找不到任何有关如何解析 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( in 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;
在工作中,我们编写了一个名为 GeoReason 的库,目标是按照 RFC-7946 规范为 GeoJSON 数据结构提供 Reason 类型、构造函数、编码器和解码器(以及一些帮助程序函数,如eq
(。
我还没有尝试过将库与 React Native 一起使用,但我认为它应该可以在任何可以编译 Reason to JS 的地方工作。
概述
- GeoJSON 对许多"或"(特征或几何,其中几何是点或线或...(关系进行建模,这些关系很容易表示为原因变体
- GeoJSON 很紧凑,更喜欢数组(作为元组(,这很难阅读。为此,我们使用原因记录。
- 我们使用 bs-解码解码值 ">
- 功能"带有额外的元数据("属性"字段(,可以是任何带有元数据的 JSON 对象......我们不会尝试在键 => json 字典之外对其进行解码:
Js.Dict.t(Js.Json.t)
用法
假设您有一个类型Js.Json.t
的 JSON 值,并且您已经按照自述文件中的说明安装了 GeoReason,您可以像这样解码和使用您的数据:
// 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 值的多边形列表(如果没有多边形,则返回空列表(。如果有其他有用的帮助程序,请随时打开问题。
您可能应该使用 GeoReason,正如@mlms13所建议的那样,但是如果您仍然想使用bs-json
自己解码它,您可以利用元组在 BuckleScript 中实现为数组的事实并使用pair
解码器获取值,然后将其map
到您的记录类型:
let coordinates = json =>
Json.Decode.(
pair(float, float)
|> map(((latitude, longitude)) => {latitude, longitude})
);