Skip to content
Permalink
Browse files

Support including attributes of related (child) features in

GeoJSON feature export

Sponsored by Kanton of Zug, Switzerland
  • Loading branch information
nyalldawson committed May 7, 2016
1 parent 34d468e commit 5c1a05c8a1fb6d52b342182161c5f8dabf4e67b0
Showing with 273 additions and 17 deletions.
  1. +31 −3 python/core/qgsjsonutils.sip
  2. +73 −5 src/core/qgsjsonutils.cpp
  3. +39 −3 src/core/qgsjsonutils.h
  4. +130 −6 tests/src/python/test_qgsjsonutils.py
@@ -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
@@ -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
@@ -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 );
};
@@ -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
{
@@ -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();
@@ -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";
@@ -115,6 +166,7 @@ QString QgsJSONExporter::exportFeature( const QgsFeature& feature, const QVarian
}



//
// QgsJSONUtils
//
@@ -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( '}' );
}

@@ -19,6 +19,7 @@
#include "qgsfeature.h"

class QTextCodec;
class QgsVectorLayer;

/** \ingroup core
* \class QgsJSONExporter
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
You can’t perform that action at this time.