Skip to content
Permalink
Browse files

Allow injecting extra properties into feature's GeoJSON export

Sponsored by Kanton of Zug, Switzerland
  • Loading branch information
nyalldawson committed May 6, 2016
1 parent c3f6c39 commit 9041c95464a5d844051df9aa450de067f7cbdd43
@@ -66,11 +66,13 @@ class QgsJSONExporter

/** Returns a GeoJSON string representation of a feature.
* @param feature feature to convert
* @param extraProperties map of extra attributes to include in feature's properties
* @param id optional ID to use as GeoJSON feature's ID instead of input feature's ID. If omitted, feature's
* ID is used.
* @returns GeoJSON string
*/
QString exportFeature( const QgsFeature& feature,
const QVariantMap& extraProperties = QVariantMap(),
const QVariant& id = QVariant() ) const;

};
@@ -26,14 +26,15 @@ QgsJSONExporter::QgsJSONExporter( int precision, bool includeGeometry, bool incl

}

QString QgsJSONExporter::exportFeature( const QgsFeature& feature, const QVariant& id ) const
QString QgsJSONExporter::exportFeature( const QgsFeature& feature, const QVariantMap& extraProperties,
const QVariant& id ) const
{
QString s = "{\n \"type\":\"Feature\",\n";

// ID
s += QString( " \"id\":%1" ).arg( !id.isValid() ? QString::number( feature.id() ) : QgsJSONUtils::encodeValue( id ) );

if ( mIncludeAttributes || mIncludeGeometry )
if ( mIncludeAttributes || mIncludeGeometry || !extraProperties.isEmpty() )
s += ",\n";
else
s += '\n';
@@ -52,32 +53,49 @@ QString QgsJSONExporter::exportFeature( const QgsFeature& feature, const QVarian
}
s += " \"geometry\":\n ";
s += geom->exportToGeoJSON( mPrecision );
if ( mIncludeAttributes )
if ( mIncludeAttributes || !extraProperties.isEmpty() )
s += ",\n";
else
s += '\n';
}

if ( mIncludeAttributes )
if ( mIncludeAttributes || !extraProperties.isEmpty() )
{
//read all attribute values from the feature
s += " \"properties\":{\n";

const QgsFields* fields = feature.fields();
int attributeCounter = 0;

for ( int i = 0; i < fields->count(); ++i )
if ( mIncludeAttributes )
{
if ( !mAttributeIndexes.isEmpty() && !mAttributeIndexes.contains( i ) )
continue;
const QgsFields* fields = feature.fields();

if ( attributeCounter > 0 )
s += ",\n";
QVariant val = feature.attributes().at( i );
for ( int i = 0; i < fields->count(); ++i )
{
if ( !mAttributeIndexes.isEmpty() && !mAttributeIndexes.contains( i ) )
continue;

s += QString( " \"%1\":%2" ).arg( fields->at( i ).name(), QgsJSONUtils::encodeValue( val ) );
if ( attributeCounter > 0 )
s += ",\n";
QVariant val = feature.attributes().at( i );

++attributeCounter;
s += QString( " \"%1\":%2" ).arg( fields->at( i ).name(), QgsJSONUtils::encodeValue( val ) );

++attributeCounter;
}
}

if ( !extraProperties.isEmpty() )
{
QVariantMap::const_iterator it = extraProperties.constBegin();
for ( ; it != extraProperties.constEnd(); ++it )
{
if ( attributeCounter > 0 )
s += ",\n";

s += QString( " \"%1\":%2" ).arg( it.key(), QgsJSONUtils::encodeValue( it.value() ) );

++attributeCounter;
}
}

s += "\n }\n";
@@ -85,11 +85,13 @@ class CORE_EXPORT QgsJSONExporter

/** Returns a GeoJSON string representation of a feature.
* @param feature feature to convert
* @param extraProperties map of extra attributes to include in feature's properties
* @param id optional ID to use as GeoJSON feature's ID instead of input feature's ID. If omitted, feature's
* ID is used.
* @returns GeoJSON string
*/
QString exportFeature( const QgsFeature& feature,
const QVariantMap& extraProperties = QVariantMap(),
const QVariant& id = QVariant() ) const;

private:
@@ -1913,7 +1913,7 @@ QString QgsWFSServer::createFeatureGeoJSON( QgsFeature* feat, int prec, QgsCoord
exporter.setIncludeAttributes( !attrsToExport.isEmpty() );
exporter.setAttributes( attrsToExport );

return exporter.exportFeature( f, id );
return exporter.exportFeature( f, QVariantMap(), id );
}

QDomElement QgsWFSServer::createFeatureGML2( QgsFeature* feat, QDomDocument& doc, int prec, QgsCoordinateReferenceSystem& crs, const QgsAttributeList& attrIndexes, const QSet<QString>& excludedAttributes ) /*const*/
@@ -248,5 +248,43 @@ def testJSONExporter(self):
}"""
self.assertEqual(exporter.exportFeature(feature, id=29), expected)

# test injecting extra attributes
expected = """{
"type":"Feature",
"id":5,
"properties":{
"name":"Valsier Peninsula",
"cost":6.8,
"population":198,
"extra":"val1",
"extra2":2
}
}"""
self.assertEqual(exporter.exportFeature(feature, extraProperties={"extra": "val1", "extra2": 2}), expected)

exporter.setIncludeAttributes(False)
expected = """{
"type":"Feature",
"id":5,
"properties":{
"extra":"val1",
"extra2":{"nested_map":5,
"nested_map2":"val"},
"extra3":[1,2,3]
}
}"""
self.assertEqual(exporter.exportFeature(feature, extraProperties={"extra": "val1", "extra2": {"nested_map": 5, "nested_map2": "val"}, "extra3": [1, 2, 3]}), expected)
exporter.setIncludeGeometry(True)
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":{
"extra":"val1",
"extra2":2
}
}"""

if __name__ == "__main__":
unittest.main()

0 comments on commit 9041c95

Please sign in to comment.
You can’t perform that action at this time.