第05章 - 数据源与输出适配器
OpenGIS DAF 通过适配器层(Adapters)屏蔽不同数据格式的差异。数据源(IFeatureSource)负责读取,输出(IFeatureSink)负责写入。本章详解内置的 4 种数据源与 4 种输出,以及它们如何在方案中配置。
5.1 适配器层架构
适配器层位于架构的第六层,向上为算子提供统一的数据访问接口,向下对接具体的数据格式:
算子池 (Operators)
│ 通过 IFeatureSource 读取 / IFeatureSink 写入
▼
适配器层 (Adapters)
├── IFeatureSource(数据源,读取)
│ ├── GeoJsonFeatureSource
│ ├── ShapefileFeatureSource
│ ├── PostgisFeatureSource
│ └── InMemoryFeatureSource
└── IFeatureSink(输出,写入)
├── ConsoleFeatureSink
├── GeoJsonFeatureSink
├── ShapefileFeatureSink
└── PostgisFeatureSink
适配器层还提供映射工具类:FieldTypeMapper(字段类型映射)、GeometryTypeMapper(几何类型映射)、PostgisConnectionHelper(PostGIS 连接辅助)。
5.2 数据源(IFeatureSource)
数据源在方案的 inputs 绑定中通过 type: external 引用。sourceId 指向文件路径或数据源标识。
5.2.1 GeoJsonFeatureSource
读取 GeoJSON / JSON 文件。
- 支持扩展名:
.geojson、.json - 特性:支持属性过滤
- 配置示例:
{
"source": { "type": "external", "sourceId": "data/schools.geojson" }
}
5.2.2 ShapefileFeatureSource
读取 ESRI Shapefile。
- 支持扩展名:
.shp - 特性:自动读取同名的
.prj文件以确定坐标系 - 配置示例:
{
"source": { "type": "external", "sourceId": "output/demo03/landuse-3857.shp" }
}
注意:Shapefile 的字段名有 10 字符限制。超过 10 字符的字段名会被截断(如
landuse_type截断为landuse_ty),且截断无法自动恢复。跨数据源方案应优先引用短字段名。
5.2.3 PostgisFeatureSource
从 PostGIS 数据库读取要素。
- 驱动:GDAL
PG:驱动 - 特性:连接密码使用 DPAPI/AES-GCM 加密,不能明文
- 配置示例(连接配置在输出绑定中,见 5.3.4)
5.2.4 InMemoryFeatureSource
内存数据源,用于算子之间的中间结果传递。当方案中一个算子的输出被标记为 isIntermediate: true 时,其结果缓存在内存中供下游算子复用,无需落盘。
5.3 输出(IFeatureSink)
输出在方案的 output 绑定中配置。adapterType 决定输出格式。
5.3.1 ConsoleFeatureSink
将要素输出到控制台。
- adapterType:
console - targetPath:忽略
- 配置示例:
{
"output": { "adapterType": "console" }
}
5.3.2 GeoJsonFeatureSink
将要素写入 GeoJSON 文件。
- adapterType:
geojson - targetPath:输出文件路径
- 配置示例:
{
"output": {
"adapterType": "geojson",
"targetPath": "output/demo01/school-service-area.geojson"
}
}
5.3.3 ShapefileFeatureSink
将要素写入 ESRI Shapefile。
- adapterType:
shapefile - targetPath:
.shp文件路径 - 特性:自动生成
.shp/.shx/.dbf/.prj/.cpg五件套 - 配置示例:
{
"output": {
"adapterType": "shapefile",
"targetPath": "output/demo03/landuse-3857.shp"
}
}
5.3.4 PostgisFeatureSink
将要素写入 PostGIS 数据库表。
- adapterType:
postgis - targetPath:目标表名
- connectionConfig:连接配置,其中
encryptedPassword必须是 DPAPI/AES 密文,不能明文 - 无覆盖策略:目标表已存在时报错
Layer already exists,不静默覆盖——这是保护生产数据的有意设计 - 配置示例:
{
"output": {
"adapterType": "postgis",
"targetPath": "school_service_area",
"connectionConfig": {
"host": "localhost",
"port": 5432,
"database": "gis",
"username": "postgres",
"encryptedPassword": "<DPAPI/AES 密文>"
}
}
}
加密说明:
encryptedPassword必须是当前用户上下文生成的 DPAPI/AES 密文。若填入占位密文,运行会立即失败并报ERR_DS_CONNECTION_FAILED(”EncryptedPassword 不是有效密文”),且错误信息不回显密文。加密机制详见docs/plan-config-guide.md与src/OpenGisDAF.Adapters/Utilities/ConnectionEncryption.cs。
5.4 adapterType 的两种写法
adapterType 支持两种写法,大小写不敏感:
- 短名:
console、geojson、shapefile、postgis - 枚举成员名:
ConsoleWriter、GeoJsonWriter、ShapefileWriter、PostGISWriter
5.5 输出 → 输入闭环
OpenGIS DAF 支持将某一步的输出文件作为后续步骤的输入源,形成”输出 → 输入”闭环。演示方案 03 展示了这一能力:第一步把 GeoJSON 转成 Shapefile 写出,第二步把刚写出的 Shapefile 作为新输入源读回做字段计算。
{
"id": "read-shp-calc",
"operatorId": "field_calculator",
"inputs": {
"source": { "type": "external", "sourceId": "output/demo03/landuse-3857.shp" }
},
"parameters": {
"target_field": "zone_desc",
"expression": "\"地块 {plot_no} | 面积 {area_ha} 公顷\"",
"field_type": "String"
},
"output": { "adapterType": "console" }
}
这使方案可以混合使用多种数据源(如 GeoJSON 输入 + Shapefile 中间产物),实现复杂的数据流转。
5.6 字段名大小写约定
框架对字段名匹配采用大小写不敏感(OrdinalIgnoreCase)策略。但需注意:
- Shapefile 读取的字段名通常为大写;
- PostGIS 写入/读取会折叠为小写;
field_calculator表达式中的字段引用是大小写敏感的。
因此跨数据源方案中,表达式里的字段引用需与实际数据源中的字段大小写保持一致。
5.7 本章小结
- 适配器层通过
IFeatureSource/IFeatureSink屏蔽数据格式差异; - 4 种数据源:GeoJSON、Shapefile、PostGIS、内存;
- 4 种输出:Console、GeoJSON、Shapefile、PostGIS;
- Shapefile 有 10 字符字段名限制,PostGIS 输出无覆盖策略(保护生产数据);
adapterType支持短名与枚举成员名两种写法;- 输出文件可作为后续输入源,形成输出 → 输入闭环,支持多数据源混用。