PostgreSQL GeoJSON <- php -> JavaScript


PostgreSQL GeoJSON <- php -> JavaScript

我正在重建一年前建造的东西(不要问旧版本去了哪里——这很尴尬)。

核心功能使用javascript中的$.getJSONajax-ish)调用,该调用运行一个PHP脚本,该脚本运行一个PostgreSQL查询,该查询构建一个JSON对象并返回它。

问题是,当轮到PostgreSQL大放异彩时,它会吐出什么。

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

目前,我正在使用row_to_json()(以及几何体上的ST_AsGeoJSON())来构建我的GeoJSON集合,该集合通过回调返回到客户端。

根据这篇非常好的帖子(并停留在该帖子的查询结构的非常小的ε内),我运行以下查询:

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变量提供)。

当我查询到$resultjson_encode($result[0]["row_to_json"])fetchAll(PDO::FETCH_ASSOC)时,返回到javascript的对象是一个对象,它可以是JSON.parse()'d来给出预期的(一个带有FeatureCollectionObject,它又包含一堆Features,其中一个是geometry)。

到目前为止,一切都很好。快速获取数据并在一秒钟左右返回

问题是,在查询阶段,与几何体相关的数组被双引号引用:单个Feature的JSON的相关段看起来像

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

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

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

"geometry":"{stuff}"

而不是

"geometry":{stuff}

如果PostgreSQL生成的JSON通过GeoJSONLint的解析器/检查器,它会死在一个尖叫的堆里(它应该死——它绝对不是"spec")——当然它永远不会呈现:正如你所期望的那样,它会吐出"无效类型"。

目前,我已经用一个笨拙的方法(我的正常M.O.)对其进行了分类——当$.getJSON返回对象时,我

  1. 把它变成一根绳子,然后
  2. .replace(/"{/g, '{').replace(/}"/g, '}').replace(/''/g, ''),然后
  3. 把它变成一个物体,然后继续恶作剧

这不是一个好的做法(至少可以说):如果可以鼓励查询本身返回有效的GeoJSON,那会好得多。

很明显,问题出在row_to_json()阶段:它看到了"几何体"的属性集,并将其与"属性"的属性集合区别对待——它(错误地)用引号转义了"几何"(在斜杠转义所有双引号之后)一个,但(正确地)保留了"属性"一个。

所以在这本书的序言之后。。。问题。

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

当然,如果有一种节省的方式来完成整个往返行程,我会接受它:唯一需要注意的是,它必须保持其"实时获取"特性——$.getJSON在谷歌地图中的"空闲"触发器下运行,源表、感兴趣的变量和缩放(决定$bounds)由用户决定。

(可以认为这是一种通过一次只获取200-300个简单的ish(地籍图)特征来更新地图层的方式,比为10-19的缩放生成整个状态的瓦片金字塔要好得多。我打赌有人已经在bl.ocks上做过这样的事情,但我还没有发现。)。

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

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

如果没有强制转换,st_asgeojson将返回一个经过双重编码的字符串。

然而,您也可以获得属性和geoJson,然后用PHP对json进行json_decode,用PHP创建geoJson featurecollection数组,最后对整个结果进行json_encode。