- GIS
- 遥感
- 数据工程
【免费下载链接】gdal
GDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.
GDAL 的ESRIJSON驱动可以直接读取符合 GeoServices REST 规范的 Feature Service 请求结果(典型实现为 ArcGIS Server REST API),并支持对跨多页的大结果集进行自动滚动读取。本文基于 GDAL 仓库中的驱动文档与源码实现,系统讲解该驱动的数据源类型、分页机制(resultOffset/resultRecordCount、FEATURE_SERVER_PAGING)、HTTP_METHOD打开选项、ESRI 字段类型到 OGR 的类型映射,以及 ESRI JSON 几何的解析规则,帮助你在命令行与编程接口中可靠地消费 ArcGIS 服务输出。
一、驱动定位与能力概览
该驱动的核心用途是读取 Feature Service 请求返回的 JSON 数据,遵循 GeoServices REST Specification,兼容 ArcGIS Server REST API 的输出格式。当结果集较大、被服务器切分到多个分页(ArcGIS Server >= 10.3)时,驱动可以自动滚动读取全部页面。
分页的启用规则(来自 驱动文档):
- 若打开的 URL不包含显式
resultOffset参数,滚动读取自动启用; - 若 URL包含
resultOffset但仍希望滚动,必须将打开选项FEATURE_SERVER_PAGING设为YES; - 页大小可用
resultRecordCount参数显式指定(受服务器上限约束);若不设置,OGR 会自动设置为服务器允许的最大值。
文档中特别强调的实操要点:分页请求要可靠工作,通常需要为某个字段加上排序子句——通常是OBJECTID,即在 URL 中添加&orderByFields=OBJECTID+ASC参数,保证服务器按确定顺序返回结果,避免滚动读取时遗漏或重复要素。
驱动注册元数据(见 ogresrijsondriver.cpp)声明了其能力:
- 矢量驱动(
GDAL_DCAP_VECTOR=YES); - 支持 Z 与 M 几何(
GDAL_DCAP_Z_GEOMETRIES=YES、GDAL_DCAP_MEASURED_GEOMETRIES=YES); - 支持虚拟 I/O(
GDAL_DCAP_VIRTUALIO=YES),因此/vsimem/等虚拟文件路径也可作为数据源; - 支持
OGRSQL与SQLITE两种 SQL 方言(GDAL_DMD_SUPPORTED_SQL_DIALECTS),可以对读入的 FeatureCollection 执行 SQL 过滤。
二、三类数据源与 ESRIJSON: 前缀
驱动接受三种数据源:
- URL——向 Web 服务发起 HTTP 请求;
- 纯文本 ESRIJSON 文件——以
.json扩展名识别; - 直接传入的 ESRI JSON 文本——例如通过
ogr.Open(text)或OGRSFDriverOpen直接传入字符串。
为消除与其他驱动(尤其是GeoJSON)的歧义,URL/文件名/文本前都可以加ESRIJSON:前缀。此外,自 GDAL 3.10 起,对支持该选项的命令行工具指定-if ESRIJSON,或在GDALOpenEx中将papszAllowedDrivers设为仅含ESRIJSON,也会强制驱动识别传入的 URL/文件名/文本。
这一行为在源码OGRESRIJSONDriverIdentify()中可以直接印证(ogresrijsondriver.cpp):当数据源被判定为 Web 服务类型时,要么是唯一允许的ESRIJSON驱动(IsSingleAllowedDriver("ESRIJSON")),要么文件名必须(不区分大小写)以ESRIJSON:开头,否则返回"不确定",让其他驱动(如GeoJSON)竞争识别。
三、打开选项:FEATURE_SERVER_PAGING 与 HTTP_METHOD
3.1 FEATURE_SERVER_PAGING
| 选项 | 取值 | 说明 |
|---|---|---|
FEATURE_SERVER_PAGING | YES、NO | 是否自动滚动读取 ArcGIS Feature Service 端点的结果。仅对 ArcGIS Server >= 10.3 且图层具备supportsPagination=true能力时生效 |
3.2 HTTP_METHOD(GDAL 3.13 起)
| 选项 | 取值 | 默认 | 说明 |
|---|---|---|---|
HTTP_METHOD | AUTO、GET、POST | AUTO | 向服务器发送请求使用的 HTTP 方法。AUTO模式下使用 GET,除非 URL 长度超过 256 字符;此时?之后的查询参数会被移到 POST 请求体中发送 |
从源码看,这两个选项都在驱动注册时通过GDAL_DMD_OPENOPTIONLIST元数据声明(ogresrijsondriver.cpp)。HTTP_METHOD的实际执行逻辑在 GeoJSON 家族共享的 HTTP 获取函数中(ogrgeojsonutils.cpp):
- 定义常量
MAX_URL_LEN_FOR_GET = 256; AUTO模式下:URL 短于 256 字符走 GET,否则自动改为 POST;- POST 模式下:把
?之后的查询串取出,塞入POSTFIELDS请求选项,URL 本体只保留到?为止。
这意味着当你的 Feature Service 查询 URL 很长(例如带复杂的where过滤表达式)时,无需手工干预,驱动会自动降级为 POST,规避部分服务器对 URL 长度的限制。
四、分页滚动的底层实现
FEATURE_SERVER_PAGING的判定与 URL 中resultOffset的交互逻辑位于OGRGeoJSONDriverOpenInternal()(ogrgeojsondriver.cpp)。核心条件是:数据源报告存在后续页(HasOtherPages()),且文件名以http开头或位于/vsimem/之下,然后按以下布尔表达式决定是否用OGRESRIFeatureServiceDataset包装数据源:
(无 resultOffset 且 FEATURE_SERVER_PAGING 未显式设为 NO) 或 (有 resultOffset 且 FEATURE_SERVER_PAGING 显式设为 YES)OGRESRIFeatureServiceDataset的构造与滚动逻辑(ogrgeojsondriver.cpp)包含三个值得注意的细节:
- 页大小的自动确定:若 URL 中未显式指定
resultRecordCount,驱动假设"服务器在首请求中返回的要素数就是其允许的最大页大小",并把这个值回填到 URL 中用于后续请求;若用户显式指定的resultRecordCount大于实际返回条数,则发出警告:Specified resultRecordCount=%d is greater than the maximum %d supported by the server。 - 滚动推进:
LoadNextPage()将resultOffset增加当前页的要素数,然后调用LoadPage(),后者用CPLURLAddKVP()把新的resultOffset拼进 URL,重新打开并解析新一页; - 复位行为:
MyResetReading()在已滚动过(m_nLastOffset > m_nFirstOffset)时会把偏移量拉回起始位置并重新加载首页,保证ResetReading()语义正确。
自动化测试用/vsimem虚拟文件完整覆盖了这一滚动路径(autotest/ogr/ogr_esrijson.py):先在内存中放置带"exceededTransferLimit": true的第一页,再放置resultOffset=1的第二页,验证GetNextFeature()能跨页依次取到 FID 1、20 两个要素;同时测试了returnCountOnly=true对应的快速GetFeatureCount()(返回{"count": 123456}),以及returnExtentOnly=true&f=geojson请求中解析bbox成员来快速获得图层范围的行为。
五、ESRI 字段类型到 OGR 的映射
OGRESRIJSONReader::ParseField()(ogresrijsonreader.cpp)负责解析响应中的fields数组并生成图层定义。ESRI 类型与 OGR 类型的映射表(源码 ogresrijsonreader.cpp)如下:
| ESRI 字段类型 | OGR 类型 | OGR 子类型 |
|---|---|---|
esriFieldTypeString | OFTString | 无 |
esriFieldTypeSingle | OFTReal | OFSTFloat32 |
esriFieldTypeDouble | OFTReal | 无 |
esriFieldTypeSmallInteger | OFTInteger | OFSTInt16 |
esriFieldTypeInteger | OFTInteger | 无 |
esriFieldTypeDate | OFTDateTime | 无 |
esriFieldTypeDateOnly | OFTDate | 无 |
esriFieldTypeTimeOnly | OFTTime | 无 |
esriFieldTypeBigInteger | OFTInteger64 | 无 |
esriFieldTypeGUID | OFTString | OFSTUUID |
esriFieldTypeGlobalID | OFTString | OFSTUUID |
几个值得留意的处理细节:
- OID 特殊处理:遇到
esriFieldTypeOID类型时,除映射为OFTInteger外,还会调用poLayer_->SetFIDColumn(pszObjName),把该字段设为要素 FID 列,后续要素的 FID 直接取自attributes中该字段的值(ogresrijsonreader.cpp); - 宽度处理:读取
length成员作为字段宽度;若宽度为INT_MAX(2147483647),源码注释指出这是"字段宽度未知"的占位值,此时不设置宽度,更符合 OGR 对 0 宽度(无限制)的表达; - 别名:
alias成员若与字段名不同,会被设为 OGR 的 alternative name; - 日期换算:ESRI 日期是毫秒级 Unix 时间戳,
EsriDateToOGRDate()将其拆解为年月日时分秒并写入OGRField(秒为 float 以容纳毫秒余数),ogresrijsonreader.cpp。
若响应中没有fields数组(某些简化的 FeatureCollection 不提供),驱动会退而求其次:先尝试fieldAliases对象;再不行则遍历各要素的attributes,按实际出现顺序推断字段名、类型与层级(嵌套属性用.分隔展平),并利用有向无环图对字段做拓扑排序,保证跨要素字段顺序稳定(ogresrijsonreader.cpp)。
六、ESRI JSON 几何格式
ESRI JSON 的几何表示与 GeoJSON 不同:点用x/y(可选z)对象,多边形用rings(带方向约定)而非 GeoJSON 的嵌套坐标数组,点集用points数组。解析入口在 ogresrijsongeometry.cpp:
OGRESRIJSONGetGeometryType()(ogresrijsongeometry.cpp)根据顶层键(x/y、rings、points等)推断几何类型;- 多边形按
rings成员读取,缺失或类型错误时报告Missing 'rings' member/Invalid 'rings' member; - 空间参考优先取几何内部的
spatialReference对象(支持wkt、latestWkt等键,测试用例test_ogr_esrijson_identify_srs即验证了从spatialReference.wkt解析出 EPSG:4326,见 autotest/ogr/ogr_esrijson.py)。
驱动在ReadLayers()中的几何类型推断策略(ogresrijsonreader.cpp)是:先用OGRESRIJSONGetGeometryType()判断整体;若为wkbNone但存在 SRS,则置为wkbUnknown;否则逐个检查features中首个带geometry成员的要素来推断,并把该几何内的spatialReference作为图层 SRS。
geometry为null的要素(测试数据中的resultOffset1即如此)会被读取为无几何的要素,不会中断滚动。测试test_ogr_esrijson_create_geometry_from_esri_json还验证了 Python 接口ogr.CreateGeometryFromEsriJson('{ "x": 2, "y": 49 }')可直接构造POINT (2 49)。
七、命令示例
文档给出的标准示例——读取一个不支持分页的 Feature Service 查询结果(驱动文档):
ogrinfo -ro -al "https://sampleserver6.arcgisonline.com/arcgis/rest/services/PoolPermits/FeatureServer/0/query?resultRecordCount=10&f=pjson"结合本文说明,一个针对支持分页(supportsPagination=true)的 ArcGIS 10.3+ 服务的更完整写法示例如下(命令格式以当前仓库文档为准,服务地址请替换为实际环境):
# 自动分页滚动:URL 不含 resultOffset,并加稳定排序 ogrinfo -ro -al "https://your.server/arcgis/rest/services/Svc/FeatureServer/0/query?where=1=1&orderByFields=OBJECTID+ASC&f=pjson" # URL 已含 resultOffset 时,用打开选项强制开启滚动 ogrinfo -ro -openoption FEATURE_SERVER_PAGING=YES -al \ "https://your.server/.../query?resultOffset=0&f=pjson" # 强制 POST 请求方法 ogrinfo -ro -openoption HTTP_METHOD=POST -al "https://your.server/.../query?where=..."测试中还展示了ogr.Open()直接打开/vsimem/下带查询参数 URL 的用法,以及直接ogr.Open(json_text)打开 ESRIJSON 文本(要求文本以 ESRI 特征字段开头),可作为编程接口参照(autotest/ogr/ogr_esrijson.py)。
八、小结
ESRIJSON驱动同时覆盖 URL、.json文件与直接文本三类数据源,配合ESRIJSON:前缀、-if ESRIJSON或papszAllowedDrivers可消除与GeoJSON驱动的识别歧义;- 分页滚动默认自动启用(URL 无
resultOffset时),FEATURE_SERVER_PAGING=YES用于在含resultOffset的 URL 上强制滚动,页大小由resultRecordCount控制并在缺省时取服务器允许的最大值;滚动依赖orderByFields保证顺序稳定性; HTTP_METHOD(GDAL 3.13 起)在 AUTO 模式下按 256 字符阈值自动在 GET/POST 间切换,长 URL 的查询参数自动移入 POST 体;- 字段类型经
goMapEsriTypeToOGR映射表精确转换为 OGR 类型(含 Float32、Int16、UUID 子类型),OID 字段自动成为 FID 列,毫秒时间戳自动换算为 OGR 日期时间; - 几何支持
x/y、rings、points等 ESRI 原生表示,SRS 可从顶层或几何内嵌spatialReference解析。
相关入口文件与测试:驱动注册、FeatureService 滚动数据集、响应解析、几何解析、自动化测试、测试数据。
- GIS
- 遥感
- 数据工程
【免费下载链接】gdal
GDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.
相关推荐
clouddragonlee/datalinkx数据映射:字段转换与类型适配
clouddragonlee/datalinkx数据映射:字段转换与类型适配 引言:数据同步的核心挑战 在异构数据源同步场景中,数据映射(Data Mappin
数据集成数据工程后端前端任务调度大模型RAGMCP 服务本地部署KeystoneJS Embedly 字段类型详解:自动抓取 oEmbed 元数据的只读字段
KeystoneJS Embedly 字段类型详解:自动抓取 oEmbed 元数据的只读字段 导读 Embedly 是 KeystoneJS 提供的一种特殊字段
后端终极Python与MySQL类型映射指南:PyMySQL数据类型转换完全解析
终极Python与MySQL类型映射指南:PyMySQL数据类型转换完全解析 PyMySQL是Python连接MySQL数据库的核心工具,它负责处理Python
数据库数据库客户端后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考