Я нахожусь в муках восстановления чего-то, что было построено почти год назад (не спрашивайте, куда делась старая версия — это неловко).
Основная функциональность использует $.getJSON
(ajax
-ish) вызов в javascript, который запускает скрипт PHP, который выполняет запрос PostgreSQL, который создает объект JSON и возвращает его. (Пауза для дыхания).
Проблема в том, что PostgreSQL выплевывает, когда наступает его очередь.
Я знаю о build_json_object()
а также build_json_array()
функциональность в PostgreSQL 9.4+, но одна из БД, на которой он должен работать, не была обновлена с 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
переменные).
Когда я fetchAll(PDO::FETCH_ASSOC)
этот запрос к $result
, а также json_encode($result[0]["row_to_json"])
, объект, возвращаемый в 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":"{stuff}"
вместо
"geometry":{stuff}
Если JSON, созданный PostgreSQL, пропускается через анализатор / средство проверки в GeoJSONLint, он умирает в кричащей куче (что и должно быть — это абсолютно не «spec») — и, конечно, он никогда не будет отображаться: он выплевывает «недопустимый тип» «Как вы могли ожидать.
На данный момент я разобрался по куче (мой обычный М.О.) — когда $.getJSON
возвращает объект, я
.replace(/"{/g, '{')
а также .replace(/}"/g, '}')
а также .replace(/\\/g, '')
, а потом Это не очень хорошая практика (если не сказать больше): было бы гораздо лучше, если бы сам запрос заставлял возвращать корректный GeoJSON.
Кажется очевидным, что проблема заключается в row_to_json()
Этап: он видит набор атрибутов для «геометрии» и обрабатывает его иначе, чем набор атрибутов для «свойств» — он (неверно) экранирует «геометрию» (после косой черты во всех двойных кавычках) один, но ( правильно) оставляет «свойства» один как есть.
Итак, после этой прелюдии на всю книгу … вопрос.
Есть ли какой-то нюанс в запросе, который я пропускаю или игнорирую? У меня есть RTFD для соответствующих команд PostgreSQL, и кроме переключателей prettification я ничего не знаю.
И, конечно, если бы существовал скупой способ совершить круговое путешествие, я бы его принял: единственное предостережение заключается в том, что он должен сохранять свою «живую» природу — $.getJSON
работает под слушателем, который запускает «холостые» на карте Google, а также исходную таблицу, представляющие интерес переменные и масштаб (который определяет $bounds
) определяются пользователем.
(Думайте об этом как о способе иметь слой карты, который обновляется с панорамированием и масштабированием, выбирая только ~ 200-300 простых (кадастровых) объектов за раз -0 намного лучше, чем генерировать пирамиду листов для целое состояние для масштабирования 10-19. Держу пари, кто-то уже сделал такую вещь на bl.ocks, но я не нашел это).
Похоже, вы пропустили актерский состав в JSON.
Так должно быть
ST_AsGeoJSON(ST_Transform(lg.g1,4326))::json
Без преобразования st_asgeojson возвращает строку с двойным кодированием.
Однако вы также можете получить атрибуты и geoJson, затем json_decode json с PHP, создать массив коллекций объектов geoJson с php и, наконец, json_encode весь результат.
Других решений пока нет …