PostgreSQL GeoJSON <- php -> JavaScript

PostgreSQL GeoJSON <- php -> JavaScript

我正处于重建将近一年前构建的东西的阵痛中(不要问旧版本去哪里了 - 这很尴尬)。

核心功能在 javascript 中使用 $.getJSONajax-ish)调用,运行 是一个 PHP 脚本 运行是一个构建 JSON 对象并 return 的 PostgreSQL 查询。 (暂停呼吸)。

问题是 PostgreSQL 在轮到它大放异彩时吐出的内容。

我知道 PostgreSQL 9.4+ 中的 build_json_object()build_json_array() 功能,但是必须 运行 的其中一个数据库尚未从 9.2 升级我在接下来的一个月左右没有时间这样做。

现在我正在使用 row_to_json()(和几何上的 ST_AsGeoJSON())来构建我的 GeoJSON 集合,它通过回调返回给客户端。

根据 this very nice post 的提示(并保持在 post 的查询结构的非常小的 epsilon 内),我 运行 以下查询:

select row_to_json(fc)
from (SELECT 'FeatureCollection' As type, 
      array_to_json(array_agg(f)) As features
from (SELECT 'Feature' as type,
      row_to_json((select l from (select $vars) as l)) as properties,
      ST_AsGeoJSON(ST_Transform(lg.g1,4326)) as geometry    
        from $source_table as lg   
 where g1 && ST_Transform(ST_SetSRID(ST_MakeEnvelope($bounds),4326),4283)
 ) as f ) as fc;

$vars$source_table$bounds 由 PHP 从 POST 变量提供)。

当我 fetchAll(PDO::FETCH_ASSOC) 查询 $resultjson_encode($result[0]["row_to_json"]) 时,return 到 javascript 的对象是一个可以 JSON.parse()' 给出预期(一个 Object 和一个 FeatureCollection 又包含一堆 Feature,其中一个是 geometry)。

到目前为止,还不错。快速 - 获取数据并在一秒钟左右返回。

问题在于,在查询阶段,与几何相关的数组是双引号的:JSON 的相关部分对于个人 Feature 看起来像

{"type":"Feature","geometry":"{\"type\":\"Polygon\",
                              \"coordinates\":"[[[146.885447408,-36.143199088],
                                               [146.884964384,-36.143136232],
                                                ... etc
                                             ]]"
                              }",
                              "properties":{"address_pfi":"126546461",
                                            "address":"blah blah",
                                             ...etc }
}

如果我将 PostgreSQL 查询结果复制到文件,这就是我得到的结果:这是在对输出进行任何错误处理之前。

注意(双转义)双引号只影响几何属性(在非JSON意义上){type, coordinates}:"geometry"位看起来像

"geometry":"{stuff}"

而不是

"geometry":{stuff}

如果 PostgreSQL 生成的 JSON 通过 GeoJSONLint 的 parser/checker,它会死在一个尖叫的堆中(它应该 - 它绝对不是 'spec') - 当然它永远不会渲染:它会像您预期的那样吐出 'invalid type'。

目前我已经把它整理出来了(我的正常 M.O。)- 当 $.getJSON return 是对象时,我

  1. 把它变成一个字符串,然后
  2. .replace(/"{/g, '{').replace(/}"/g, '}').replace(/\/g, ''),然后是
  3. 将其变回物体并继续进行恶作剧。

这不是好的做法(至少可以说):如果可以鼓励查询本身 return 有效 GeoJSON.

会好得多

很明显,问题出在 row_to_json() 阶段:它看到 "geometry" 的属性集,并将其与 "properties" 的属性集区别对待 - 它(错误地)引号转义 "geometry" (在斜线转义所有双引号之后)一个但(正确地)保留 "properties" 一个原样。

所以在这本书长度的前奏之后...问题。

我遗漏或忽略的查询有什么细微差别吗?我有相关 PostgreSQL 命令的 RTFD,除了美化开关之外,我什么都不知道。

当然,如果有一种简洁的方式来完成整个往返行程,我会接受它:唯一的警告是它必须保留其 'live-fetch' 性质 - $.getJSON 运行s 在 Google 地图中触发 "idle" 的侦听器下,源 table、感兴趣的变量和缩放(确定 $bounds)是用户-决定。

(将其视为一种通过平移和缩放更新地图图层的方法,一次仅获取约 200-300 个简单的(地籍)特征 -0 比生成要好得多缩放 10-19 的整个状态的平铺金字塔。我打赌有人已经在 bl.ocks 上做过这样的事情,但我还没有找到它)。

您似乎缺少对 json 的转换。 应该是

ST_AsGeoJSON(ST_Transform(lg.g1,4326))::json

没有转换,st_asgeojson returns 一个字符串,即双重编码。

但是,您还可以获得属性和 geoJson,而不是 json_decode json 和 PHP,创建一个 geoJson featurecollection 数组 php,最后 json_encode 整个结果。