Skip to content

Commit

Permalink
Support including attributes of related (child) features in
Browse files Browse the repository at this point in the history
GeoJSON feature export

Sponsored by Kanton of Zug, Switzerland
  • Loading branch information
nyalldawson committed May 9, 2016
1 parent 34d468e commit 5c1a05c
Show file tree
Hide file tree
Showing 4 changed files with 273 additions and 17 deletions.
34 changes: 31 additions & 3 deletions python/core/qgsjsonutils.sip
Expand Up @@ -12,11 +12,10 @@ class QgsJSONExporter
public:

/** Constructor for QgsJSONExporter.
* @param vectorLayer associated vector layer (required for related attribute export)
* @param precision maximum number of decimal places to use for geometry coordinates
* @param includeGeometry set to false to avoid including the geometry representation in the JSON output
* @param includeAttributes set to false to avoid including any attribute values in the JSON output
*/
QgsJSONExporter( int precision = 17, bool includeGeometry = true, bool includeAttributes = true );
QgsJSONExporter( const QgsVectorLayer* vectorLayer = nullptr, int precision = 17 );

/** Sets the maximum number of decimal places to use in geometry coordinates.
* @param precision number of decimal places
Expand Down Expand Up @@ -51,6 +50,30 @@ class QgsJSONExporter
*/
bool includeAttributes() const;

/** Sets whether to include attributes of features linked via references in the JSON exports.
* @param includeRelated set to true to include attributes for any related child features
* within the exported properties element.
* @note associated vector layer must be set with setVectorLayer()
* @see includeRelated()
*/
void setIncludeRelated( bool includeRelated );

/** Returns whether attributes of related (child) features will be included in the JSON exports.
* @see setIncludeRelated()
*/
bool includeRelated() const;

/** Sets the associated vector layer (required for related attribute export).
* @param vectorLayer vector layer
* @see vectorLayer()
*/
void setVectorLayer( const QgsVectorLayer* vectorLayer );

/** Returns the associated vector layer, if set.
* @see setVectorLayer()
*/
QgsVectorLayer* vectorLayer() const;

/** Sets the list of attributes to include in the JSON exports.
* @param attributes list of attribute indexes, or an empty list to include all
* attributes
Expand Down Expand Up @@ -138,4 +161,9 @@ class QgsJSONUtils
* @returns encoded value
*/
static QString encodeValue( const QVariant& value );

/** Exports all attributes from a QgsFeature as a JSON map type.
* @param feature feature to export
*/
static QString exportAttributes( const QgsFeature& feature );
};
78 changes: 73 additions & 5 deletions src/core/qgsjsonutils.cpp
Expand Up @@ -16,16 +16,32 @@
#include "qgsjsonutils.h"
#include "qgsogrutils.h"
#include "qgsgeometry.h"
#include "qgsvectorlayer.h"
#include "qgsmaplayerregistry.h"
#include "qgsrelation.h"
#include "qgsrelationmanager.h"
#include "qgsproject.h"


QgsJSONExporter::QgsJSONExporter( int precision, bool includeGeometry, bool includeAttributes )
QgsJSONExporter::QgsJSONExporter( const QgsVectorLayer* vectorLayer, int precision )
: mPrecision( precision )
, mIncludeGeometry( includeGeometry )
, mIncludeAttributes( includeAttributes )
, mIncludeGeometry( true )
, mIncludeAttributes( true )
, mIncludeRelatedAttributes( false )
, mLayerId( vectorLayer ? vectorLayer->id() : QString() )
{

}

void QgsJSONExporter::setVectorLayer( const QgsVectorLayer* vectorLayer )
{
mLayerId = vectorLayer ? vectorLayer->id() : QString();
}

QgsVectorLayer *QgsJSONExporter::vectorLayer() const
{
return qobject_cast< QgsVectorLayer* >( QgsMapLayerRegistry::instance()->mapLayer( mLayerId ) );
}

QString QgsJSONExporter::exportFeature( const QgsFeature& feature, const QVariantMap& extraProperties,
const QVariant& id ) const
{
Expand All @@ -37,7 +53,6 @@ QString QgsJSONExporter::exportFeature( const QgsFeature& feature, const QVarian
{
//read all attribute values from the feature


if ( mIncludeAttributes )
{
const QgsFields* fields = feature.fields();
Expand Down Expand Up @@ -70,7 +85,43 @@ QString QgsJSONExporter::exportFeature( const QgsFeature& feature, const QVarian
++attributeCounter;
}
}

// related attributes
QgsVectorLayer* vl = vectorLayer();
if ( vl && mIncludeRelatedAttributes )
{
QList< QgsRelation > relations = QgsProject::instance()->relationManager()->referencedRelations( vl );
Q_FOREACH ( const QgsRelation& relation, relations )
{
if ( attributeCounter > 0 )
properties += ",\n";

QgsFeatureRequest req = relation.getRelatedFeaturesRequest( feature );
req.setFlags( QgsFeatureRequest::NoGeometry );
QgsVectorLayer* childLayer = relation.referencingLayer();
QString relatedFeatureAttributes;
if ( childLayer )
{
QgsFeatureIterator it = childLayer->getFeatures( req );
QgsFeature relatedFet;
int relationFeatures = 0;
while ( it.nextFeature( relatedFet ) )
{
if ( relationFeatures > 0 )
relatedFeatureAttributes += ",\n";

relatedFeatureAttributes += QgsJSONUtils::exportAttributes( relatedFet );
relationFeatures++;
}
}
relatedFeatureAttributes.prepend( '[' ).append( ']' );

properties += QString( " \"%1\":%2" ).arg( relation.name(), relatedFeatureAttributes );
attributeCounter++;
}
}
}

bool hasProperties = attributeCounter > 0;

QString s = "{\n \"type\":\"Feature\",\n";
Expand Down Expand Up @@ -115,6 +166,7 @@ QString QgsJSONExporter::exportFeature( const QgsFeature& feature, const QVarian
}



//
// QgsJSONUtils
//
Expand Down Expand Up @@ -194,3 +246,19 @@ QString QgsJSONUtils::encodeValue( const QVariant &value )
return v.prepend( '"' ).append( '"' );
}
}

QString QgsJSONUtils::exportAttributes( const QgsFeature& feature )
{
const QgsFields* fields = feature.fields();
QString attrs;
for ( int i = 0; i < fields->count(); ++i )
{
if ( i > 0 )
attrs += ",\n";

QVariant val = feature.attributes().at( i );
attrs += encodeValue( fields->at( i ).name() ) + ':' + encodeValue( val );
}
return attrs.prepend( '{' ).append( '}' );
}

42 changes: 39 additions & 3 deletions src/core/qgsjsonutils.h
Expand Up @@ -19,6 +19,7 @@
#include "qgsfeature.h"

class QTextCodec;
class QgsVectorLayer;

/** \ingroup core
* \class QgsJSONExporter
Expand All @@ -31,11 +32,10 @@ class CORE_EXPORT QgsJSONExporter
public:

/** Constructor for QgsJSONExporter.
* @param vectorLayer associated vector layer (required for related attribute export)
* @param precision maximum number of decimal places to use for geometry coordinates
* @param includeGeometry set to false to avoid including the geometry representation in the JSON output
* @param includeAttributes set to false to avoid including any attribute values in the JSON output
*/
QgsJSONExporter( int precision = 17, bool includeGeometry = true, bool includeAttributes = true );
QgsJSONExporter( const QgsVectorLayer* vectorLayer = nullptr, int precision = 17 );

/** Sets the maximum number of decimal places to use in geometry coordinates.
* @param precision number of decimal places
Expand Down Expand Up @@ -70,6 +70,30 @@ class CORE_EXPORT QgsJSONExporter
*/
bool includeAttributes() const { return mIncludeAttributes; }

/** Sets whether to include attributes of features linked via references in the JSON exports.
* @param includeRelated set to true to include attributes for any related child features
* within the exported properties element.
* @note associated vector layer must be set with setVectorLayer()
* @see includeRelated()
*/
void setIncludeRelated( bool includeRelated ) { mIncludeRelatedAttributes = includeRelated; }

/** Returns whether attributes of related (child) features will be included in the JSON exports.
* @see setIncludeRelated()
*/
bool includeRelated() const { return mIncludeRelatedAttributes; }

/** Sets the associated vector layer (required for related attribute export).
* @param vectorLayer vector layer
* @see vectorLayer()
*/
void setVectorLayer( const QgsVectorLayer* vectorLayer );

/** Returns the associated vector layer, if set.
* @see setVectorLayer()
*/
QgsVectorLayer* vectorLayer() const;

/** Sets the list of attributes to include in the JSON exports.
* @param attributes list of attribute indexes, or an empty list to include all
* attributes
Expand Down Expand Up @@ -115,6 +139,7 @@ class CORE_EXPORT QgsJSONExporter
const QVariantMap& extraProperties = QVariantMap(),
const QVariant& id = QVariant() ) const;


private:

//! Maximum number of decimal places for geometry coordinates
Expand All @@ -133,6 +158,12 @@ class CORE_EXPORT QgsJSONExporter
//! Whether to include attributes in JSON export
bool mIncludeAttributes;

//! Whether to include attributes from related features in JSON export
bool mIncludeRelatedAttributes;

//! Layer ID of associated vector layer. Required for related attribute export.
QString mLayerId;

};

/** \ingroup core
Expand Down Expand Up @@ -171,6 +202,11 @@ class CORE_EXPORT QgsJSONUtils
*/
static QString encodeValue( const QVariant& value );

/** Exports all attributes from a QgsFeature as a JSON map type.
* @param feature feature to export
*/
static QString exportAttributes( const QgsFeature& feature );

};

#endif // QGSJSONUTILS_H

0 comments on commit 5c1a05c

Please sign in to comment.