Skip to content

Introduction

As a background you might want first to check a good introduction about OGC API Features or a video about the OGC API standard family, both provided by OGC (The Open Geospatial Consortium) itself.

The following diagram describes a decision flowchart to select a client class and a feature source to access GeoJSON feature collections and feature items:

Below you can find few step-by-step instructions how to get started in scenarios represented in the decision flowchart.

πŸ’» Static GeoJSON local resource

// 1. Get a feature source using an accessor to a file.
final source = GeoJSONFeatures.any(() async => File('...').readAsString());
// 2. Access feature items.
final items = await source.itemsAll();
// 3. Get an iterable of feature objects.
final features = items.collection.features;
// 4. Loop through features (each with id, properties and geometry)
for (final feat in features) {
print('Feature ${feat.id} with geometry: ${feat.geometry}');
}

🌐 Static GeoJSON web resource

// 1. Get a feature source from a web resource using http.
final source = GeoJSONFeatures.http(location: Uri.parse('...'));
// 2. Access feature items.
final items = await source.itemsAll();
// 3. Get an iterable of feature objects.
final features = items.collection.features;
// 4. Loop through features (each with id, properties and geometry)
for (final feat in features) {
print('Feature ${feat.id} with geometry: ${feat.geometry}');
}

🌎 Web API service conforming to OGC API Features

// 1. Get a client instance for a Web API endpoint.
final client = OGCAPIFeatures.http(endpoint: Uri.parse('...'));
// 2. Access/check metadata (meta, OpenAPI, conformance, collections) as needed.
final conformance = await client.conformance();
if (!conformance.conformsToFeaturesCore(geoJSON: true)) {
return; // not conforming to core and GeoJSON - so return
}
// 3. Get a feature source for a specific collection.
final source = await client.collection('my_collection');
// 4. Access (and check) metadata for this collection.
final meta = await source.meta();
print('Collection title: ${meta.title}');
// 5. Access feature items.
final items = await source.itemsAll(limit: 100);
// 6. Check response metadata.
print('Timestamp: ${items.timeStamp}');
// 7. Get an iterable of feature objects.
final features = items.collection.features;
// 8. Loop through features (each with id, properties and geometry)
for (final feat in features) {
print('Feature ${feat.id} with geometry: ${feat.geometry}');
}

For the step 5 other alternatives are:

  • Use source.items() to get feature items by a filtered query (ie. bbox).
  • Use source.itemById() to get a single feature by an identifier.
  • Use source.itemsAllPaged() or source.itemsPaged() for accessing paged feature sets.

In the step 6 it’s also possible to get links to related resources, and optionally also to get a number of matched or returned features in a response.

πŸ” Using the standard HTTP RetryClient

When accessing static GeoJSON web resources or an OGC API Features service, it’s also possible to define a retry policy using the standard http package. However you must also manage the life cycle of such a HTTP client instance by ensuring it’s closed after making API calls.

A sample accessing OGC API Features service with custom HTTP client:

// Create an instance of the standard HTTP retry client for API calls
final httpClient = RetryClient(http.Client(), retries: 4);
try {
// 1. Get a client instance for a Web API endpoint.
final client = OGCAPIFeatures.http(
// set HTTP client (if not set the default `http.Client()` is used)
client: httpClient,
// an URI to the landing page of the service
endpoint: Uri.parse('...'),
);
// 2. Access/check metadata (meta, OpenAPI, conformance, collections) as needed.
final conformance = await client.conformance();
if (!conformance.conformsToFeaturesCore(geoJSON: true)) {
return; // not conforming to core and GeoJSON - so return
}
// 3. Get a feature source for a specific collection.
final source = await client.collection('my_collection');
// ... other steps just like previously demonstrated ...
} finally {
// ensure the HTTP client is closed after using
httpClient.close();
}

This example of using a retry client requires also following imports:

import 'package:http/http.dart' as http;
import 'package:http/retry.dart';