【发布时间】:2021-05-16 03:06:57
【问题描述】:
目前我有一个从特定 API 请求 JSONS 的程序。 API 的创建者声称此数据在 GeoJSON 中,但 QGIS 无法读取。
所以我想扩展我的 Python 脚本以将 JSON 以可读格式转换为 GEOJSON 以进入 QGIS 并在那里进一步处理。
但是,我有一些问题, 一个我不知道从哪里开始以及 JSON 文件是如何构建的......它有点混乱。 JSONS 实际上是基于两个 API Get Request 制作的。第一个 Api Get Request 请求点数,第二个请求点数的详细信息。有关更多上下文,请参见此处的此问题: API Request within another API request (Same API) in Python
请注意,由于字数限制,我无法在此处发布代码:
这些细节当然应该是这些点周围区域的“轮廓”。 问题是.. JSON 中提到了点本身,因此很难指定每个点的坐标。更不用说我们感兴趣的所有其他属性,都在 GeoJSON 的“点”部分。
看看 JSON 本身就明白我的意思了:
{
"comment": null,
"contactDetails": {
"city": null,
"country": "BE",
"email": null,
"extraAddressInfo": null,
"firstName": null,
"kboNumber": null,
"lastName": "TMVW",
"number": null,
"organisation": "TMVW - Brugge-Kust",
"phoneNumber1": null,
"phoneNumber2": null,
"postalCode": null,
"street": null
},
"contractor": null,
"description": "WEGENISWERKEN - Oostende - 154-W - H Baelskaai-project Oosteroever",
"diversions": [],
"endDateTime": "2021-06-30T00:00:00",
"gipodId": 1042078,
"hindrance": {
"description": null,
"direction": null,
"effects": [
"Omleiding: beide richtingen",
"Afgesloten: volledige rijweg",
"Fietsers hebben geen doorgang",
"Handelaars bereikbaar",
"Plaatselijk verkeer: toegelaten",
"Voetgangers hebben doorgang"
],
"important": true,
"locations": [
"Voetpad",
"Fietspad",
"Parkeerstrook",
"Rijbaan"
]
},
"latestUpdate": "2020-12-01T12:16:00.03",
"location": {
"cities": [
"Oostende"
],
"coordinate": {
"coordinates": [
2.931988215468502,
51.23633810341717
],
"crs": {
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
},
"type": "name"
},
"type": "Point"
},
"geometry": {
"coordinates": [
[
[
2.932567101705748,
51.23657315009855
],
[
2.9309934586397337,
51.235776874431004
],
[
2.9328606392338914,
51.2345112414401
],
[
2.9344086040607285,
51.23535468563417
],
[
2.9344709862243095,
51.23529463700852
],
[
2.932928489694045,
51.23447026126373
],
[
2.935453674897618,
51.2326691257775
],
[
2.937014893295095,
51.23347469462423
],
[
2.9370649363167556,
51.23342209549579
],
[
2.9355339718818847,
51.23261689467634
],
[
2.937705787093551,
51.23108125372614
],
[
2.939235922008332,
51.23191301940206
],
[
2.9393162149112086,
51.231860784836144
],
[
2.9377921292631313,
51.23102909334536
],
[
2.9395494398210404,
51.22978103014327
],
[
2.9395326861153492,
51.22973522407282
],
[
2.9307116955342982,
51.23588365892173
],
[
2.93077732400986,
51.235914858980586
],
[
2.930921969180147,
51.23581685905391
],
[
2.932475593354336,
51.23662429379119
],
[
2.932567101705748,
51.23657315009855
]
]
],
"crs": {
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
},
"type": "name"
},
"type": "Polygon"
}
},
"mainContractor": null,
"owner": "TMVW - Brugge-Kust",
"reference": "DOM-154/15/004-W",
"startDateTime": "2017-05-02T00:00:00",
"state": "In uitvoering",
"type": "Wegeniswerken (her)aanleg",
"url": null
}
提醒一下,这些 JSON 不应该是点文件,并且几何可以是多边形,如上所示:多多边形或多线串(此处没有示例)。
那么我该如何开始,并确保我不仅获得了细节属性,而且还清楚地了解了轮廓几何和坐标?
唯一的唯一 ID 是 GIPOD ID,因为这是此 API 数据库中实际链接所在的位置。
编辑 1:
所以这就是所谓的 geojson 标准。
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
}
根据这个标准,转换后的JSON应该是这样的:
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
2.932567101705748,
51.23657315009855
],
[
2.9309934586397337,
51.235776874431004
],
[
2.9328606392338914,
51.2345112414401
],
[
2.9344086040607285,
51.23535468563417
],
[
2.9344709862243095,
51.23529463700852
],
[
2.932928489694045,
51.23447026126373
],
[
2.935453674897618,
51.2326691257775
],
[
2.937014893295095,
51.23347469462423
],
[
2.9370649363167556,
51.23342209549579
],
[
2.9355339718818847,
51.23261689467634
],
[
2.937705787093551,
51.23108125372614
],
[
2.939235922008332,
51.23191301940206
],
[
2.9393162149112086,
51.231860784836144
],
[
2.9377921292631313,
51.23102909334536
],
[
2.9395494398210404,
51.22978103014327
],
[
2.9395326861153492,
51.22973522407282
],
[
2.9307116955342982,
51.23588365892173
],
[
2.93077732400986,
51.235914858980586
],
[
2.930921969180147,
51.23581685905391
],
[
2.932475593354336,
51.23662429379119
],
[
2.932567101705748,
51.23657315009855
]
]
},
"properties": {
Too much columns to type, cannot claim them all here because of character limit.
}
}
编辑 3:提供的解决方案是朝着正确方向迈出的良好一步,但它给我带来了两个问题:
- 保存的几何是 Null,使这个 JSON 成为一个没有 几何。
- 仅保存 1 个数据点,而不是所有已保存的数据点 正在请求中。
这是 JSON:
{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": null, "properties": {"gipodId": 3099549, "StartDateTime": null, "EndDateTime": null, "state": null, "location": {"cities": ["Waregem", "Wielsbeke"], "coordinate": {"coordinates": [3.4206971887218445, 50.91662742195287], "type": "Point", "crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}}}}}}]}
Python 代码:下面看看它已经走了多远:
import requests
import json
import os
import glob
import shutil
def process_location_data(location_json):
"""Converts the data point into required geojson format"""
# assigning variable to store geometry details
geometery_details = location_json.get("location").get("geometery")
#geometery_details.pop("crs") # removes the "crs" from geometry
# includes city and location_coordinates
location_details = {
"cities": location_json.get("location").get("cities"),
"coordinate": location_json.get("location").get("coordinate")
}
#EndDateTime
end_datetime = location_json.get("EndDateTime")
#StarDateTime
start_datetime = location_json.get("StarDateTime")
#State
state = location_json.get("State")
#gipodId
gipod_id = location_json.get("gipodId")
#adding all these details into another dict
properties = {
"gipodId": gipod_id,
"StartDateTime": start_datetime,
"EndDateTime": end_datetime,
"state": state,
"location": location_details
}
# creating the final dict to be returned.
geojson_data_point = {
"type": "Feature",
"geometry" : geometery_details,
"properties": properties
}
return geojson_data_point
def process_all_location_data(all_location_points):
"""
For all the points in the location details we will
create the feature collection
"""
feature_collection = {
"type": "FeatureCollection",
"features": []
} #creates dict with zero features.
for data_point in all_location_points:
feature_collection.get("features").append(
process_location_data(data_point)
)
return feature_collection
def fetch_details(url: str, file_name: str):
# Makes request call to get the data of detail
response = requests.get(url)
print("Sending Request for details of gpodId: " + file_name)
folder_path ='api_request_jsons/fetch_details/JSON unfiltered'
text = json.dumps(response.json(),sort_keys=False, indent=4)
print("Details extracted for: "+ file_name)
save_file(folder_path,file_name,text)
return response.json()
# save_file(folder_path,GipodId,text2)
# any other processe
def fetch_points(url: str):
response = requests.get(url)
folder_path ='api_request_jsons/fetch_points'
text = json.dumps(response.json(),sort_keys=False, indent=4)
print("Points Fetched, going to next step: Extracting details")
for obj in response.json():
all_location_points = [fetch_details(obj.get("detail"),str(obj.get("gipodId")))]
save_file(folder_path,'points',text)
feature_collection_json = process_all_location_data(all_location_points)
text2 = json.dumps(process_all_location_data(all_location_points))
folder_path2 = "api_request_jsons/fetch_details/Coordinates"
file_name2 = "Converted"
save_file(folder_path2,file_name2,text2)
return feature_collection_json
def save_file(save_path: str, file_name: str, file_information: str):
completeName = os.path.join(save_path, file_name +".json")
print(completeName + " saved")
file1 = open(completeName, "wt")
file1.write(file_information)
file1.close()
api_response_url = "http://api.gipod.vlaanderen.be/ws/v1/workassignment"
fetch_points(api_response_url)
【问题讨论】:
-
嗨,Joerie,让我试着了解一下挑战。这里你想只提取每个数据点的位置键形式json,还是只提取位置的几何形状?
-
如果可能的话,位置和几何形状,更不用说稍后在 QGIS 中翻译的其他属性。它只需要在 QGIS 中可读(在 GeoJSON 中转换),包括其他属性和属性。如果这太难了,可以将非位置日期拆分为单独的 CSV 文件,稍后通过唯一 GIODID 加入它们。最佳场景、位置坐标、几何、StarDateTime、EndDateTime 和状态。生成 GeoJSON。
-
不同特征集合中的位置坐标和几何形状或相同?我对geo json没有经验。你能分享一个预期结果的样本吗?如果我有这些供参考,我将能够更有效地提供帮助。
-
正如我在 Polygon/MultiPolygon/MultiString 的几何和位置之前所述。一会儿为它“应该看起来”如何创建一个例子。基于 Geojson 标准。