无法将几何图形转换为GeoJSON

5

我的问题是这样的。我正在为一些数据创建一个模型。

class Cables(Base):
    __tablename__ = 'cables'

    id = Column(Integer, nullable=False)
    route = Column(Geometry(geometry_type='LINESTRING', srid=4326), nullable=False)

现在,我想将这样一条路线转换为GeoJSON格式。
我尝试过的方法:
@app.route("/api/cable/<int:id>", methods=['GET'])
def get_cable(id):
    cable = session.query(Cables).filter(Cables.id == id).first()
    return str(geoalchemy2.functions.ST_AsGeoJSON(cable.route))

返回值为ST_AsGeoJSON(ST_GeomFromEWKB(:ST_GeomFromEWKB_1))

如果我更改返回值:

return geoalchemy2.functions.ST_AsGeoJSON(cable.route)

返回 TypeError: 'ST_AsGeoJSON'对象不可调用


(涉及 IT 技术)
return str(cable.route)

返回 0102000020e610000002000000b34fd4d9bca351c032e14d5134c240c0d24f8055e0a351c0dedea9f4dcbf40c0,这意味着我有一个几何对象。

return cable.route

返回 TypeError: 'WKBElement' 对象不可调用

如果我打印路由类型,

print(type(cable.route))

返回结果
<class 'geoalchemy2.elements.WKBElement'>

我认为它应该返回这个类的一个对象,而不是类本身。我现在感到困惑,不知道该怎么办了。你有什么建议吗?
3个回答

6

似乎正确的调用ST_AsGeoJSON的方式是在查询内部。例如,

ruta = session.query(Cables.route.ST_AsGeoJSON()).filter(Cables.id == id).first()

我最终做的是安装一个新库(shapely),以便读取十六进制字节字符串,然后将其转换为字典,因为字典可以很容易地转换为json。
def ewkb_route_to_dict(self):
    """
    returns the cable's route as a dictionary.
    It uses shapely.wkb.loads. The first argument is the route as a bytestring,
    and the second one (True) is to tell loads that
    the input wkb will be represented as a hex string
    """
    return mapping(shapely.wkb.loads(str(self.route), True))

然后在我的toString方法中:

def __str__(self):
    d = dict()
    ...
    d["route"] = self.ewkb_route_to_dict()
    ...
    return dumps(d)

这将正确地将几何图形转换为GeoJSON格式。


能否在返回几何信息时同时返回名称或ID?我也遇到了类似的问题;https://gis.stackexchange.com/questions/297713/geojson-feature-collection - user3342735

2

我知道这篇文章已经有点旧了,但是对于那些仍然遇到这个问题的人,以下是我的解决方案:

import ast
from flask.json import jsonify
from sqlalchemy import func

@app.route("/api/cable/<int:id>", methods=['GET'])
def get_cable(id):
    geom = session.query(func.ST_AsGeoJSON(Cables.route)).filter(Cables.id == id).scalar()
    # The code below makes a geojson with CRS.
    # See http://www.postgis.org/docs/ST_AsGeoJSON.html for more details.
    #geom = session.query(func.ST_AsGeoJSON(Cables.route,15,2)).filter(Cables.id == id).scalar()
    return jsonify(ast.literal_eval(geom))

能否在返回几何信息时同时返回名称或ID?我也遇到了类似的问题;https://gis.stackexchange.com/questions/297713/geojson-feature-collection - user3342735
scalar()将返回第一行的第一列,如果您想要其他列,可以使用all()代替,但在这种情况下将返回一行的列表。session.query(Cables.id, Cables.other_data, func.ST_AsGeoJSON(Cables.route)).filter(Cables.id == id).all() - Jair Perrut
结果在控制台中显示,URL出现500内部服务器错误。有什么建议吗? - user3342735
你能粘贴一下异常描述吗? - Jair Perrut

1

在文档中, PostGIS友好地提醒您:

ST_AsGeoJSON仅构建几何图形,您需要自己从Postgres表中构建其余的Feature

实际上,尝试将ST_AsGeoJSON的输出发送到Leaflet图层将失败,因为它不是有效的Feature。虽然文档提供了25行PostGIS代码,但在SQLAlchemy中使用它并不吸引人。我发现最简单的方法是使用一个小型Python库shapely-geojson

$ pip install shapely-geojson

然后在你的代码中:

from shapely_geojson import dumps, Feature
from geoalchemy2.shape import to_shape

cable = session.query(Cables).filter(Cables.id == id).first()
feature = Feature(to_shape(cable[0]))
geoJSON = dumps(feature)

请注意,GeoJSON标准在2016年进行了更改,以强制执行右手定则。根据您的数据中线或多边形的结构以及接收软件的挑剔程度,您可能需要使用geojson_rewind来更改点的顺序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接