Navigation Menu

Skip to content

Commit

Permalink
Refactor to move JSON exporter to its own class
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed May 9, 2016
1 parent 935f4ad commit c3f6c39
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 57 deletions.
96 changes: 78 additions & 18 deletions python/core/qgsjsonutils.sip
@@ -1,3 +1,81 @@
/** \ingroup core
* \class QgsJSONExporter
* \brief Handles exporting QgsFeature features to GeoJSON features.
* \note Added in version 2.16
*/

class QgsJSONExporter
{
%TypeHeaderCode
#include <qgsjsonutils.h>
%End
public:

/** Constructor for QgsJSONExporter.
* @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 );

/** Sets the maximum number of decimal places to use in geometry coordinates.
* @param precision number of decimal places
* @see precision()
*/
void setPrecision( int precision );

/** Returns the maximum number of decimal places to use in geometry coordinates.
* @see setPrecision()
*/
int precision() const;

/** Sets whether to include geometry in the JSON exports.
* @param includeGeometry set to false to prevent geometry inclusion
* @see includeGeometry()
*/
void setIncludeGeometry( bool includeGeometry );

/** Returns whether geometry will be included in the JSON exports.
* @see setIncludeGeometry()
*/
bool includeGeometry() const;

/** Sets whether to include attributes in the JSON exports.
* @param includeAttributes set to false to prevent attribute inclusion
* @see includeAttributes()
*/
void setIncludeAttributes( bool includeAttributes );

/** Returns whether attributes will be included in the JSON exports.
* @see setIncludeAttributes()
*/
bool includeAttributes() 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
* @see attributes()
*/
void setAttributes( const QgsAttributeList& attributes );

/** Returns the list of attributes which will be included in the JSON exports, or
* an empty list if all attributes will be included.
* @see setAttributes()
*/
QgsAttributeList attributes() const;

/** Returns a GeoJSON string representation of a feature.
* @param feature feature to convert
* @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 QVariant& id = QVariant() ) const;

};


/** \ingroup core
* \class QgsJSONUtils
* \brief Helper utilities for working with JSON and GeoJSON conversions.
Expand Down Expand Up @@ -31,24 +109,6 @@ class QgsJSONUtils
*/
static QgsFields stringToFields( const QString& string, QTextCodec* encoding );

/** Returns a GeoJSON string representation of a feature.
* @param feature feature to convert
* @param precision maximum number of decimal places to use for geometry coordinates
* @param attrIndexes list of attribute indexes to include in GeoJSON, or an empty list to include
* all attributes
* @param includeGeom 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
* @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
*/
static QString featureToGeoJSON( const QgsFeature& feature,
int precision = 17,
const QgsAttributeList& attrIndexes = QgsAttributeList(),
bool includeGeom = true,
bool includeAttributes = true,
const QVariant& id = QVariant() );

/** Encodes a value to a JSON string representation, adding appropriate quotations and escaping
* where required.
* @param value value to encode
Expand Down
57 changes: 33 additions & 24 deletions src/core/qgsjsonutils.cpp
Expand Up @@ -17,54 +17,48 @@
#include "qgsogrutils.h"
#include "qgsgeometry.h"

QgsFeatureList QgsJSONUtils::stringToFeatureList( const QString &string, const QgsFields &fields, QTextCodec *encoding )
{
return QgsOgrUtils::stringToFeatureList( string, fields, encoding );
}

QgsFields QgsJSONUtils::stringToFields( const QString &string, QTextCodec *encoding )
QgsJSONExporter::QgsJSONExporter( int precision, bool includeGeometry, bool includeAttributes )
: mPrecision( precision )
, mIncludeGeometry( includeGeometry )
, mIncludeAttributes( includeAttributes )
{
return QgsOgrUtils::stringToFields( string, encoding );

}

QString QgsJSONUtils::featureToGeoJSON( const QgsFeature& feature,
int precision,
const QgsAttributeList& attrIndexes,
bool includeGeom,
bool includeAttributes,
const QVariant& id )
QString QgsJSONExporter::exportFeature( const QgsFeature& feature, const QVariant& id ) const
{
QString s = "{\n \"type\":\"Feature\",\n";

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

if ( includeAttributes || includeGeom )
if ( mIncludeAttributes || mIncludeGeometry )
s += ",\n";
else
s += '\n';

const QgsGeometry* geom = feature.constGeometry();
if ( geom && !geom->isEmpty() && includeGeom )
if ( geom && !geom->isEmpty() && mIncludeGeometry )
{
QgsRectangle box = geom->boundingBox();

if ( QgsWKBTypes::flatType( geom->geometry()->wkbType() ) != QgsWKBTypes::Point )
{
s += QString( " \"bbox\":[%1, %2, %3, %4],\n" ).arg( qgsDoubleToString( box.xMinimum(), precision ),
qgsDoubleToString( box.yMinimum(), precision ),
qgsDoubleToString( box.xMaximum(), precision ),
qgsDoubleToString( box.yMaximum(), precision ) );
s += QString( " \"bbox\":[%1, %2, %3, %4],\n" ).arg( qgsDoubleToString( box.xMinimum(), mPrecision ),
qgsDoubleToString( box.yMinimum(), mPrecision ),
qgsDoubleToString( box.xMaximum(), mPrecision ),
qgsDoubleToString( box.yMaximum(), mPrecision ) );
}
s += " \"geometry\":\n ";
s += geom->exportToGeoJSON( precision );
if ( includeAttributes )
s += geom->exportToGeoJSON( mPrecision );
if ( mIncludeAttributes )
s += ",\n";
else
s += '\n';
}

if ( includeAttributes )
if ( mIncludeAttributes )
{
//read all attribute values from the feature
s += " \"properties\":{\n";
Expand All @@ -74,14 +68,14 @@ QString QgsJSONUtils::featureToGeoJSON( const QgsFeature& feature,

for ( int i = 0; i < fields->count(); ++i )
{
if ( !attrIndexes.isEmpty() && !attrIndexes.contains( i ) )
if ( !mAttributeIndexes.isEmpty() && !mAttributeIndexes.contains( i ) )
continue;

if ( attributeCounter > 0 )
s += ",\n";
QVariant val = feature.attributes().at( i );

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

++attributeCounter;
}
Expand All @@ -94,6 +88,21 @@ QString QgsJSONUtils::featureToGeoJSON( const QgsFeature& feature,
return s;
}


//
// QgsJSONUtils
//

QgsFeatureList QgsJSONUtils::stringToFeatureList( const QString &string, const QgsFields &fields, QTextCodec *encoding )
{
return QgsOgrUtils::stringToFeatureList( string, fields, encoding );
}

QgsFields QgsJSONUtils::stringToFields( const QString &string, QTextCodec *encoding )
{
return QgsOgrUtils::stringToFields( string, encoding );
}

QString QgsJSONUtils::encodeValue( const QVariant &value )
{
if ( value.isNull() )
Expand Down
88 changes: 88 additions & 0 deletions src/core/qgsjsonutils.h
Expand Up @@ -20,6 +20,94 @@

class QTextCodec;

/** \ingroup core
* \class QgsJSONExporter
* \brief Handles exporting QgsFeature features to GeoJSON features.
* \note Added in version 2.16
*/

class CORE_EXPORT QgsJSONExporter
{
public:

/** Constructor for QgsJSONExporter.
* @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 );

/** Sets the maximum number of decimal places to use in geometry coordinates.
* @param precision number of decimal places
* @see precision()
*/
void setPrecision( int precision ) { mPrecision = precision; }

/** Returns the maximum number of decimal places to use in geometry coordinates.
* @see setPrecision()
*/
int precision() const { return mPrecision; }

/** Sets whether to include geometry in the JSON exports.
* @param includeGeometry set to false to prevent geometry inclusion
* @see includeGeometry()
*/
void setIncludeGeometry( bool includeGeometry ) { mIncludeGeometry = includeGeometry; }

/** Returns whether geometry will be included in the JSON exports.
* @see setIncludeGeometry()
*/
bool includeGeometry() const { return mIncludeGeometry; }

/** Sets whether to include attributes in the JSON exports.
* @param includeAttributes set to false to prevent attribute inclusion
* @see includeAttributes()
*/
void setIncludeAttributes( bool includeAttributes ) { mIncludeAttributes = includeAttributes; }

/** Returns whether attributes will be included in the JSON exports.
* @see setIncludeAttributes()
*/
bool includeAttributes() const { return mIncludeAttributes; }

/** 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
* @see attributes()
*/
void setAttributes( const QgsAttributeList& attributes ) { mAttributeIndexes = attributes; }

/** Returns the list of attributes which will be included in the JSON exports, or
* an empty list if all attributes will be included.
* @see setAttributes()
*/
QgsAttributeList attributes() const { return mAttributeIndexes; }

/** Returns a GeoJSON string representation of a feature.
* @param feature feature to convert
* @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 QVariant& id = QVariant() ) const;

private:

//! Maximum number of decimal places for geometry coordinates
int mPrecision;

//! List of attribute indexes to include in export, or empty list to include all attributes
QgsAttributeList mAttributeIndexes;

//! Whether to include geometry in JSON export
bool mIncludeGeometry;

//! Whether to include attributes in JSON export
bool mIncludeAttributes;

};

/** \ingroup core
* \class QgsJSONUtils
* \brief Helper utilities for working with JSON and GeoJSON conversions.
Expand Down
12 changes: 8 additions & 4 deletions src/server/qgswfsserver.cpp
Expand Up @@ -1868,13 +1868,16 @@ QString QgsWFSServer::createFeatureGeoJSON( QgsFeature* feat, int prec, QgsCoord
{
QString id = QString( "%1.%2" ).arg( mTypeName, FID_TO_STRING( feat->id() ) );

QgsJSONExporter exporter;
exporter.setPrecision( prec );

//copy feature so we can modify its geometry as required
QgsFeature f( *feat );
const QgsGeometry* geom = feat->constGeometry();
bool withGeom = false;
exporter.setIncludeGeometry( false );
if ( geom && mWithGeom && mGeometryName != "NONE" )
{
withGeom = true;
exporter.setIncludeGeometry( true );
if ( mGeometryName == "EXTENT" )
{
QgsRectangle box = geom->boundingBox();
Expand Down Expand Up @@ -1907,9 +1910,10 @@ QString QgsWFSServer::createFeatureGeoJSON( QgsFeature* feat, int prec, QgsCoord
attrsToExport << idx;
}

bool withAttributes = !attrsToExport.isEmpty();
exporter.setIncludeAttributes( !attrsToExport.isEmpty() );
exporter.setAttributes( attrsToExport );

return QgsJSONUtils::featureToGeoJSON( f, prec, attrsToExport, withGeom, withAttributes, id );
return exporter.exportFeature( f, id );
}

QDomElement QgsWFSServer::createFeatureGML2( QgsFeature* feat, QDomDocument& doc, int prec, QgsCoordinateReferenceSystem& crs, const QgsAttributeList& attrIndexes, const QSet<QString>& excludedAttributes ) /*const*/
Expand Down

0 comments on commit c3f6c39

Please sign in to comment.