第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

将要素输出到控制台。

  • adapterTypeconsole
  • targetPath:忽略
  • 配置示例
{
  "output": { "adapterType": "console" }
}

5.3.2 GeoJsonFeatureSink

将要素写入 GeoJSON 文件。

  • adapterTypegeojson
  • targetPath:输出文件路径
  • 配置示例
{
  "output": {
    "adapterType": "geojson",
    "targetPath": "output/demo01/school-service-area.geojson"
  }
}

5.3.3 ShapefileFeatureSink

将要素写入 ESRI Shapefile。

  • adapterTypeshapefile
  • targetPath.shp 文件路径
  • 特性:自动生成 .shp/.shx/.dbf/.prj/.cpg 五件套
  • 配置示例
{
  "output": {
    "adapterType": "shapefile",
    "targetPath": "output/demo03/landuse-3857.shp"
  }
}

5.3.4 PostgisFeatureSink

将要素写入 PostGIS 数据库表。

  • adapterTypepostgis
  • 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.mdsrc/OpenGisDAF.Adapters/Utilities/ConnectionEncryption.cs

5.4 adapterType 的两种写法

adapterType 支持两种写法,大小写不敏感:

  1. 短名consolegeojsonshapefilepostgis
  2. 枚举成员名ConsoleWriterGeoJsonWriterShapefileWriterPostGISWriter

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 支持短名与枚举成员名两种写法;
  • 输出文件可作为后续输入源,形成输出 → 输入闭环,支持多数据源混用。

← 上一章 返回目录 下一章 →