Skip to content

Commit 139185d

Browse files
committed
feat: add function to decode feature properties
Signed-off-by: Aleksei Gurianov <[email protected]>
1 parent 05dee2e commit 139185d

File tree

2 files changed

+109
-1
lines changed

2 files changed

+109
-1
lines changed

src/gleojson.gleam

+32-1
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,6 @@ fn geometry_decoder(
267267
}
268268
}
269269

270-
/// Decodes a FeatureId from a dynamic value.
271270
fn feature_id_decoder(
272271
dyn_value: dynamic.Dynamic,
273272
) -> Result(FeatureId, List(dynamic.DecodeError)) {
@@ -377,3 +376,35 @@ pub fn geojson_decoder(dyn_value) -> Result(GeoJSON, List(dynamic.DecodeError))
377376
_ -> result.map(geometry_decoder(dyn_value), GeoJSONGeometry)
378377
}
379378
}
379+
380+
/// Retrieves and decodes a specific property from a Feature's properties.
381+
///
382+
/// This function attempts to extract a property with the given key from the Feature's
383+
/// properties dictionary and decode it using the provided decoder.
384+
///
385+
/// ## Example
386+
///
387+
/// ```gleam
388+
/// let properties = option.Some(dict.from_list([#("height", dynamic.from(10.5))]))
389+
/// let result = get_feature_property(properties, "height", dynamic.float)
390+
/// // result will be Ok(10.5) if successful
391+
/// ```
392+
///
393+
/// Note: This function will return an Error if the properties are None,
394+
/// if the key is not found in the properties, or if the decoder fails.
395+
pub fn get_feature_property(
396+
properties: option.Option(dict.Dict(String, dynamic.Dynamic)),
397+
key: String,
398+
decoder: dynamic.Decoder(a),
399+
) -> Result(a, List(dynamic.DecodeError)) {
400+
case properties {
401+
option.Some(properties) -> {
402+
dict.get(properties, key)
403+
}
404+
_ -> Error(Nil)
405+
}
406+
|> result.map_error(fn(_) {
407+
[dynamic.DecodeError(expected: "Property", found: "Invalid", path: [key])]
408+
})
409+
|> result.try(decoder)
410+
}

test/gleojson_test.gleam

+77
Original file line numberDiff line numberDiff line change
@@ -466,3 +466,80 @@ pub fn geometrycollection_example_test() {
466466

467467
assert_decode(json_string, expected_geojson)
468468
}
469+
470+
pub fn feature_decode_properties_test() {
471+
let json_string =
472+
"
473+
{
474+
\"type\": \"Feature\",
475+
\"geometry\": {
476+
\"type\": \"Point\",
477+
\"coordinates\": [102.0, 0.5]
478+
},
479+
\"properties\": {
480+
\"prop0\": \"value0\",
481+
\"prop1\": 0.0,
482+
\"prop2\": {
483+
\"this\": \"that\"
484+
},
485+
\"prop3\": [1, 2, 3],
486+
\"prop4\": true,
487+
\"prop5\": null
488+
}
489+
}
490+
"
491+
492+
let decoded_result =
493+
json.decode(from: json_string, using: gleojson.geojson_decoder)
494+
495+
let assert Ok(gleojson.GeoJSONFeature(gleojson.Feature(
496+
geometry,
497+
properties,
498+
id,
499+
))) = decoded_result
500+
501+
geometry
502+
|> should.be_some
503+
|> should.equal(gleojson.Point([102.0, 0.5]))
504+
505+
id
506+
|> should.be_none
507+
508+
gleojson.get_feature_property(properties, "prop0", dynamic.string)
509+
|> should.be_ok
510+
|> should.equal("value0")
511+
512+
gleojson.get_feature_property(properties, "prop1", dynamic.float)
513+
|> should.be_ok
514+
|> should.equal(0.0)
515+
516+
gleojson.get_feature_property(
517+
properties,
518+
"prop2",
519+
dynamic.dict(of: dynamic.string, to: dynamic.string),
520+
)
521+
|> should.be_ok
522+
|> should.equal(dict.from_list([#("this", "that")]))
523+
524+
gleojson.get_feature_property(properties, "prop3", dynamic.list(dynamic.int))
525+
|> should.be_ok
526+
|> should.equal([1, 2, 3])
527+
528+
gleojson.get_feature_property(properties, "prop4", dynamic.bool)
529+
|> should.be_ok
530+
|> should.equal(True)
531+
532+
gleojson.get_feature_property(
533+
properties,
534+
"prop5",
535+
dynamic.optional(dynamic.dynamic),
536+
)
537+
|> should.be_ok
538+
|> should.equal(option.None)
539+
540+
gleojson.get_feature_property(properties, "missing", dynamic.string)
541+
|> should.be_error
542+
543+
gleojson.get_feature_property(properties, "prop0", dynamic.float)
544+
|> should.be_error
545+
}

0 commit comments

Comments
 (0)