Wie erstelle ich ein JSON in SQLAlchemy?

Django, Flask, Bottle, WSGI, CGI…
Antworten
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Hallo,

Ich benutze SQLAlchemy mit dem Modul cx_Oracle um mich mit meiner Oracle Datenbank zu verbinden!
Im nächsten Schritt erstelle ich meine Tabelle. Danach führe ich den Query aus:

Code: Alles auswählen

import cx_Oracle
import json
from sqlalchemy import create_engine
from sqlalchemy import select
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey

engine = create_engine('oracle+cx_oracle://TEST_3D:limo1013@10.40.33.160:1521/sdetest')

conn = engine.connect()

metadata = MetaData(engine)

a = Table('building', metadata, autoload=True )
b = Table('thematic_surface', metadata, autoload=True )
d = Table('surface_geometry', metadata, autoload=True )
e = Table('objectclass', metadata, autoload=True )

result2 = conn.execute("SELECT a.id AS building_nr, c.Geometry AS geometry, d.Classname AS polygon_typ FROM   building a, THEMATIC_SURFACE b, SURFACE_GEOMETRY c, OBJECTCLASS d  WHERE  a.grid_id_400 = 4158 AND a.id = b.BUILDING_ID AND b.LOD2_MULTI_SURFACE_ID = c.ROOT_ID AND c.GEOMETRY IS NOT NULL AND b.OBJECTCLASS_ID = d.ID")
Hier ist mein Ergebnis:
  • (1508351, <cx_Oracle.OBJECT object at 0x02EF7460>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02F3C7A0>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02EF7460>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02F3C720>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02EF7460>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02F3C7A0>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02EF7460>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02F3C720>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02EF7460>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02F3C7A0>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02EF7460>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02F3C720>, 'BuildingWallSurface')
    (1508351, <cx_Oracle.OBJECT object at 0x02EF7460>, 'BuildingGroundSurface')
Was ist ein cx_Oracle.OBJECT?
Kann SQLAlchemy Geometrien aus einer Datenbank lesen oder muss ich die Erweiterung GeoAlchemy nutzen?
Geht das auch mit web.py? Bei PostgreSQL habe ich es mit Web.py gemacht. Aber Web.py unterstützt nicht Oracle. Von daher nutze ich SQLAlchemy.
Mein Ziel ist ein JSON aus dem Ergebnis zu erstellen.
Zuletzt geändert von Anonymous am Montag 11. Juli 2016, 16:55, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@moehre: Warum verwendest Du SQLAlchemy wenn Du das dann gar nicht verwendest? Die Zeilen 11 bis 17 sind überflüssig, weil die dort definierten Objekte nirgends verwendet werden, und in Zeile 18 machst Du dann eine Abfrage mit reinem SQL in einer Zeichenkette für die man kein SQLAlchemy bräuchte.

SQLAlchemy gibt Dir da einfach das Objekt von der Anbindung weiter, also in diesem Fall `cx_Oracle`, wenn es mit dem Datentyp auf Datenbankseite nichts anfangen kann. Da müsstest Du dann bei `cx_Oracle` in der Dokumentation schauen ob und wie man bei Datentypen die kein Standard-SQL sind, an die Werte kommt.

Falls GeoAlchemy Unterstützt was Du da machen willst, wäre das natürlich auch eine Option. Aber eigentlich erst wenn Du wirklich SQLAlchemy verwenden willst. Bringt ja nichts eine Zwischenschicht da rein zu hauen und dann um sie herum zu programmieren.
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Sorry ich bin in der Materie noch sehr unerfahren!
Ich habe es ein bischen umgestellt.

Code: Alles auswählen

import cx_Oracle
from sqlalchemy import create_engine
from sqlalchemy.sql import select
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.orm import *

engine = create_engine('oracle+cx_oracle://TEST_3D:limo1013@10.40.33.160:1521/sdetest')

metadata = MetaData(engine)

conn = engine.connect()


a = Table('building', metadata,GeometryExtensionColumn('centroid_geom', Geometry(2)), autoload=True )
b = Table('thematic_surface', metadata, autoload=True )
d = Table('surface_geometry', metadata, autoload=True )
e = Table('objectclass', metadata, autoload=True )

s = select([a.c.id]) #selectbuilding.id from building
result = conn.execute(s)

for row in result:
    print row
Ich verwende SQL Expression API. Ich will nur das er mir ein SQL-statement an die vorhandene Datenbank schickt, die Tabellen lädt und dann die Abfrage ausführt. Laut der Doku gibt es mehrere Verfahren entweder Engine API (rohe SQL statements), SQL Expression API und Object Relational API!

Mein SQL Statement lautet:
SELECT a.id AS building_nr, c.Geometry AS geometry, d.Classname AS polygon_typ
FROM building a, THEMATIC_SURFACE b, SURFACE_GEOMETRY c, OBJECTCLASS d
WHERE a.grid_id_400 = 4158 AND a.id = b.BUILDING_ID AND b.LOD2_MULTI_SURFACE_ID = c.ROOT_ID AND c.GEOMETRY IS NOT NULL AND b.OBJECTCLASS_ID = d.ID

Wie kann ich den für mich umformulieren? Weiß jemand zufällig wie das geht innerhalb des select (s = select([a.c.id])) statements?
Das Ergebnis soll später als JSON zurückgegeben werden...
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

ist es etwas in der Richtung?:

Code: Alles auswählen

s = select([a.c.id, d.c.geometry, e.c.classname], a.c.grid_id_400 == 4158 and a.c.id == b.c.building_id and b.c.LOD2_MULTI_SURFACE_ID == d.c.ROOT_ID and d.c.GEOMETRY != NULL and b.c.objectclass_id == e.c.ID)
Die Abfrage läuft zwar aber das Ergebnis passt irgendwie nicht!
Zuletzt geändert von Anonymous am Dienstag 12. Juli 2016, 13:25, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@moehre: ``and`` und ``or`` lassen sich in Python nicht überladen, dementsprechend haben werden die von Python ausgewertet bevor die Abfrage ausgeführt wird. Ich glaube ``&`` und ``|`` sind von SQLAlchemy überladen, aber ich verwende immer die Funktionen `and_()` und `or_()` von SQLAlchemy. Dann braucht man sich keine Gedanken über Operatorvorrang machen.
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Ok meinst du so etwas:

Code: Alles auswählen

s = select([a.c.id, d.c.geometry, e.c.classname]),(and_(a.c.grid_id_400 == 4158, a.c.id == b.c.building_id, b.c.LOD2_MULTI_SURFACE_ID == d.c.ROOT_ID, d.c.GEOMETRY != NONE, b.c.objectclass_id == e.c.ID))
Nur es funktioniert nicht! Machst du das ganze mit einem query-Objekt anstelle eines select Befehls?
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Ich habe es:

Code: Alles auswählen

import cx_Oracle
from sqlalchemy import create_engine
from sqlalchemy.sql import select
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.orm import *
from geoalchemy  import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.sql import and_

engine = create_engine('oracle+cx_oracle://TEST_3D:limo1013@10.40.33.160:1521/sdetest')

metadata = MetaData(engine)

conn = engine.connect()

Session = sessionmaker(bind=engine)
session = Session()

a = Table('building', metadata,GeometryExtensionColumn('centroid_geom', Geometry(2)), autoload=True, autoload_with=engine )
b = Table('thematic_surface', metadata, autoload=True )
d = Table('surface_geometry', metadata, autoload=True )
e = Table('objectclass', metadata, autoload=True )

s = select([a.c.id, d.c.geometry, e.c.classname]).where(and_(a.c.grid_id_400 == 4158, a.c.id == b.c.building_id, b.c.lod2_multi_surface_id == d.c.root_id, d.c.geometry!= None, b.c.objectclass_id == e.c.id))#selectbuilding.id from building

result = conn.execute(s)

for row in result:
    print row
Zum Schluss kriege ich mein gewünschtes Ergebnis:

(1508351.0, <cx_Oracle.OBJECT object at 0x03329EA0>, u'BuildingWallSurface')
(1508351.0, <cx_Oracle.OBJECT object at 0x0330B660>, u'BuildingWallSurface')
(1508351.0, <cx_Oracle.OBJECT object at 0x03329EE0>, u'BuildingWallSurface')
(1508351.0, <cx_Oracle.OBJECT object at 0x0330B660>, u'BuildingWallSurface')
(1508351.0, <cx_Oracle.OBJECT object at 0x03329EA0>, u'BuildingWallSurface')
(1508351.0, <cx_Oracle.OBJECT object at 0x0330B660>, u'BuildingWallSurface')
(1508351.0, <cx_Oracle.OBJECT object at 0x03329EE0>, u'BuildingWallSurface')
(1508351.0, <cx_Oracle.OBJECT object at 0x0330B660>, u'BuildingWallSurface')
(1508351.0, <cx_Oracle.OBJECT object at 0x03329EA0>, u'BuildingWallSurface')
(1508351.0, <cx_Oracle.OBJECT object at 0x0330B660>, u'BuildingGroundSurface')
.....................................
..................................

Genau das habe ich gesucht. Jetzt stellt sich mir nur die Frage wie ich diesen Output in ein JSON konvertieren kann.
Wenn da jemand etwas weiß wäre ich sehr dankbar...

Ich kann normale SQL Objekte in JSON konvertieren mit :

Code: Alles auswählen

import json
print json.dumps([dict(r) for r in result])
Mein Problem ist die Spalte d.c.geometry-> die Geometrien kann er nicht parsen!!!
BlackJack

@moehre: Die Importe sind ziemlich unübersichtlich. Du importierst Sachen die nicht verwendet werden explizit und eine Menge über Sternchenimporte implizit.

Der ORM-Kram ist überflüssig weil er nicht verwendet wird.

Die Verbindung wird ziemlich weit vor der ersten Verwendung erstellt.

Die Namen `a` bis `e` sind sagen dem Leser nichts über die Bedeutung des Wertes.

Wenn die Namen besser wären, würde es Sinn machen den Code für die Abfrage lesbarer zu formatieren.

Ich lande dann bei so etwas (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
from sqlalchemy import create_engine
from sqlalchemy import Table, MetaData
from sqlalchemy.sql import and_, select
from geoalchemy import Geometry, GeometryExtensionColumn


def main():
    engine = create_engine(
        'oracle+cx_oracle://TEST_3D:limo1013@10.40.33.160:1521/sdetest'
    )
    metadata = MetaData(engine)
    building = Table(
        'building',
        metadata,
        GeometryExtensionColumn('centroid_geom', Geometry(2)),
        autoload=True,
        autoload_with=engine
    )
    thematic_surface = Table('thematic_surface', metadata, autoload=True)
    surface_geometry = Table('surface_geometry', metadata, autoload=True)
    objectclass = Table('objectclass', metadata, autoload=True)

    connection = engine.connect()
    query = select(
        [building.c.id, surface_geometry.c.geometry, objectclass.c.classname]
    ).where(
        and_(
            building.c.grid_id_400 == 4158,
            building.c.id == thematic_surface.c.building_id,
            thematic_surface.c.lod2_multi_surface_id
                == surface_geometry.c.root_id,
            surface_geometry.c.geometry != None,
            thematic_surface.c.objectclass_id == objectclass.c.id,
        )
    )
    for row in connection.execute(query):
        print(row)


if __name__ == '__main__':
    main()
”Normale” SQL-Objekte kann Du auch nur so zu JSON konvertieren solange es Werte sind für die das `json`-Modul eine Abbildung zu JSON kennt. BLOBs, TIME, DATE, und DATETIME könnten da zum Beispiel auch zum Problem werden, auch wenn die Standard-SQL sind. Du musst halt herausfinden wie Du diese `cx_Oracle.OBJECT` verwendet. Also entweder in der Dokumentation nachlesen und/oder interaktiv in einer Python-Shell mal untersuchen was die so an Attributen/Methoden haben.
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Ich kann die Koordinaten eines cx_Oracle.Object ausgeben mit:

Code: Alles auswählen

print result2.SDO_ORDINATES
Ergebnis:
[3500983.087, 5394211.455, 473.82800000000003, 3500978.97, 5394211.04, 469.069,
3500979.85, 5394201.47, 468.482, 3500984.777, 5394202.055, 474.192, 3500983.087,
5394211.455, 473.82800000000003]


Ich will nur das er mir daraus ein JSON bzw. GEOJSON erzeugt dazu finde ich nichts...
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Ich habe eine Idee.
Es gibt eine Funktion sdo2geojson http://spatialdbadvisor.com/oracle_spat ... do2geojson!
Damit kann ich in sql developer geojson erzeugen. Wie kann ich die Funktion in das python script laden?
Dort steht Funktion nicht definiert beim Ausführen.
BlackJack

@moehre: Da musst Du schauen wie man in SQLAlchemy oder `cx_Oracle` auf Datenbankseite Funktionen erstellt und wie man die dann aufruft. Man könnte aber auch versuchen zu verstehen was diese ”SQL”-Funktion macht und das in Python implementieren.
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Die letzte veröffetnlichte Version von cx_Oracle (5.2.1) kann nicht mit Oracle Objekten umgehen
In der neuen Version ist dies möglich.
Die unreleased Version kann bereits runtergeladen werden-> https://bitbucket.org/anthony_tuininga/cx_oracle

Mein Ziel war es ein Webservice zu erstellen. Dieser sieht jetzt wie folgt aus:

Code: Alles auswählen

import cx_Oracle
import json
import web
 
urls = (
  "/", "index",
  "/bbox", "bbox",
  )
app = web.application(urls, globals())
web.config.debug = True
 
 
def ObjectRepr(obj):
    if obj.type.iscollection:
        returnValue = []
        for value in obj.aslist():
            if isinstance(value, cx_Oracle.Object):
                value = ObjectRepr(value)
            returnValue.append(value)
    else:
        returnValue = {}
        for attr in obj.type.attributes:
            value = getattr(obj, attr.name)
            if value is None:
                continue
            elif isinstance(value, cx_Oracle.Object):
  value = ObjectRepr(value)
  if attr.name == "SDO_ORDINATES":
  returnValue['"type":"Polygon","coordinates"'] = value
    return returnValue
 
class Test(object):
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
 
connection = cx_Oracle.Connection("TEST_3D/limo1013@10.40.33.160:1521/sdetest")
typeObj = connection.gettype("MDSYS.SDO_GEOMETRY")
 
class index:
    def GET(self):
       return "hallo moritz "
 
class bbox:
  def GET(self):
       web.header('Access-Control-Allow-Origin',      '*')
       web.header('Access-Control-Allow-Credentials', 'true')
       web.header('Content-Type', 'application/json')
 
       cursor = connection.cursor()
       cursor.execute("""SELECT a.id ,c.Geometry  , d.Classname  FROM   building a, THEMATIC_SURFACE b, SURFACE_GEOMETRY c, OBJECTCLASS d  WHERE  a.grid_id_400 = 4158 AND a.id = b.BUILDING_ID AND b.LOD2_MULTI_SURFACE_ID = c.ROOT_ID AND                          c.GEOMETRY IS NOT NULL AND b.OBJECTCLASS_ID = d.ID""")
       cursor.rowfactory = Test
       for row in cursor:
            return json.dumps(('"building_nr": %s, "geometry": %s, "polygon_typ": %s"' % (row.a, ObjectRepr(row.b), row.c)))
 
if __name__ == "__main__":
       app.run()
Result in the Browser:
"\"building_nr\": 1318140, \"geometry\": {'\"type\":\"Polygon\",\"coordinates\"': [3500983.087, 5394211.455, 473.82800000000003, 3500978.97, 5394211.04, 469.069, 3500979.85, 5394201.47, 468.482, 3500984.777, 5394202.055, 474.192, 3500983.087, 5394211.455, 473.82800000000003]}, \"polygon_typ\": BuildingRoofSurface\""

Es funktioniert also. Mittels der neuen Version und der Funktion def ObjectRepr() erstelle ich aus den cx_Oracle.Objects dieses JSON!
BlackJack

@moehre: Falls das so wirklich funktioniert, also das JSON tatsächlich *so* aussehen soll, dann ist das IMHO sehr eigenartig und unerwartet aufgebaut. Das hat ja überhaupt keine Struktur und besteht nur aus einem einzigen Wert, nämlich *einer* Zeichenkette deren Inhalt selbst entfernt an JSON erinnert.
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Ja ich habe mich auch gewundert. Es sieht komisch aus

Wenn ich diesen Code nehme sieht es gut aus:

Code: Alles auswählen

r = [dict((d[0], v) for d, v in zip(cursor.description, r)) for r in cursor]
	json_output = json.dumps(r)
	return json.dumps(r)
Das Ergebnis sieht gut aus:
[{"BUILDING_NR": 1508351, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1508254, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1508161, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1508161, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1508110, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1508110, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1508034, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1507953, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1507953, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1507924, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1507924, "POLYGON_TYPE": "BuildingRoofSurface"}, {"BUILDING_NR": 1507903, "POLYGON_TYPE": "BuildingRoofSurface"},...

SELECT a.id AS building_nr , d.Classname AS polygon_type

Ich habe jetzt habe nur building_nr und polygon_type abgefragt.
Mit der Geometrie (SELECT a.id AS building_nr , c.Geometry AS geometry, d.Classname AS polygon_type...) geht die oben dargestellte Iteration nicht mehr. Wie kann ich das c.Geometrie Objekt mit der Funktion ObjectRepr() in dieser Iteration umwandeln?
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@moehre: eine for-Schleife, deren Körper nur aus einem return besteht, sieht seltsam aus. Da weiß der Leser nicht, ob das so gewollt und nicht gekonnt ist, oder ob es sich um einen Fehler handelt.

Wie ich gerade sehe, willst Du doch eine Liste als Ergebnis haben. Also wolltest Du etwas in der Art schreiben;

Code: Alles auswählen

cursor.execute("""SELECT a.id, c.Geometry, d.Classname
    FROM building a, THEMATIC_SURFACE b, SURFACE_GEOMETRY c, OBJECTCLASS d
    WHERE  a.grid_id_400 = :1
    AND a.id = b.BUILDING_ID AND b.LOD2_MULTI_SURFACE_ID = c.ROOT_ID
    AND c.GEOMETRY IS NOT NULL AND b.OBJECTCLASS_ID = d.ID""", [4158])
result = []
for id, geometry, classname in cursor:
    result.append({
        "building_nr": id, "geometry": {
            "type": "polygon",
            "coordinates": geometry.SDO_ORDINATES.aslist(),
        }, "polygon_typ": classname,
    })
return json.dumps(result)
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Oh ok geht das wirklich so einfach?

Wenn ich dein Code ausprobiere kommt folgende Fehlermeldung:
ORA-21500: Interner Fehlercode, Argumente: [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s]

Nur wenn ich die Geometrie weglasse funktioniert es wieder.

In der Python Konsole:
>>> geometry.SDO_ORDINATES
<cx_Oracle.Object MDSYS.SDO_ORDINATE_ARRAY at 0x2533de8>

>>> geometry.SDO_ORDINATES.aslist()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
cx_Oracle.DatabaseError: OCI-21500: Interner Fehlercode, Argumente: [19708], [],
[], [], [], [], [], []
OCI-21500: Interner Fehlercode, Argumente: [kope2upic2954], [54], [155], [0], []
, [], [], []
OCI-21500: Interner Fehlercode, Argumente: [19708], [], [], [], [], [], [], []

Was bedeutet das???
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Ok ich weiß jetzt wo der Fehler liegt!
In der cx_Oracle Doku steht, dass das Cursor Object eine default Größe von 50 (cursor.arraysize) besitzt!
Das heißt er greift nur 50 Reihen von der Abfrage ab und überträgt sie zum Client.
Wenn ich die arraysize vom Cursor erhöhe werden alle Ergebnisse dargestellt.

Dieser Internal Server Error bezieht sich somit auf die Cursor.arraysize!

Code: Alles auswählen

class grid:
	def GET(self):	
		web.header('Access-Control-Allow-Origin',      '*')
		web.header('Access-Control-Allow-Credentials', 'true')		
		web.header('Content-Type', 'application/json')
		
		
		cursor = connection.cursor()
		cursor.arraysize = 5000 # default = 50
		cursor.execute("""SELECT a.id , c.geometry, d.Classname FROM   building a, THEMATIC_SURFACE b, SURFACE_GEOMETRY c, OBJECTCLASS d  WHERE  a.grid_id_400 = 4148 AND a.id = b.BUILDING_ID AND b.LOD2_MULTI_SURFACE_ID = c.ROOT_ID AND c.GEOMETRY IS NOT NULL AND b.OBJECTCLASS_ID = d.ID""")
		
		
		result = []
		for id, geometry, classname in cursor:
			result.append({
			"building_nr": id, "geometry": {
				"type": "polygon",
				"coordinates": geometry.SDO_ORDINATES.aslist(),
				}, "polygon_typ": classname,
			})
		return json.dumps(result)
Wenn ich alternativ diesen code verwenden will kommt bei Geometrie null raus. Wisst ihr vielleicht wieso?:

Code: Alles auswählen

def GeometryObj(obj):
	coordinates = []
	sourceCoordinates = obj.SDO_ORDINATES.aslist()
	
	for i in range(len(sourceCoordinates) // 3):
		coordinates.append(sourceCoordinates[i * 3:i * 3 + 3])
	return

Code: Alles auswählen

		result = []
		for id, geometry, classname in cursor:
			result.append({
			"building_nr": id, "geometry": {
				"type": "polygon",
				"coordinates": GeometryObj(geometry),
				}, "polygon_typ": classname,
			})
		return json.dumps(result)
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Ahh ich habe vergessen beim return coordinates anzugeben!
So jetzt funktioniert es optimal....:)

Output:
[{"building_nr": 936948, "geometry": {"type": "polygon", "coordinates": [[3496994.34, 5394340.43, 440.82500000000005], [3496994.18, 5394336.51, 440.92], [3496998.89, 5394336.19, 440.68800000000005], [3496999.1, 5394339.13, 440.612], [3496997.82, 5394339.22, 440.675], [3496997.89, 5394340.19, 440.65000000000003], [3496994.34, 5394340.43, 440.82500000000005]]}, "polygon_typ": "BuildingRoofSurface"},
{"building_nr": 936948, "geometry": {"type": "polygon", "coordinates": [[3496999.1, 5394339.13, 440.612], [3496998.89, 5394336.19, 440.68800000000005], [3496998.89, 5394336.19, 438.27], [3496999.1, 5394339.13, 438.27], [3496999.1, 5394339.13, 440.612]]}, "polygon_typ": "BuildingWallSurface"}, {"building_nr": 936948, "geometry": {"type": "polygon", "coordinates": [[3496997.82, 5394339.22, 440.675], [3496999.1, 5394339.13, 440.612], [3496999.1, 5394339.13, 438.27], [3496997.82, 5394339.22, 438.27], [3496997.82, 5394339.22, 440.675]]}, "polygon_typ": "BuildingWallSurface"}]
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@moehre: schau mal Dein "return" an.

Code: Alles auswählen

def geometry_to_points(obj):
    return zip(*[iter(obj.SDO_ORDINATES.aslist())]*3)
moehre
User
Beiträge: 39
Registriert: Donnerstag 21. April 2016, 13:50

Alles klar danke ;)
Antworten