QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsjsonutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsjsonutils.h
3  -------------
4  Date : May 206
5  Copyright : (C) 2016 Nyall Dawson
6  Email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsjsonutils.h"
17 #include "qgsogrutils.h"
18 #include "qgsgeometry.h"
19 #include "qgsvectorlayer.h"
20 #include "qgsmaplayerregistry.h"
21 #include "qgsrelation.h"
22 #include "qgsrelationmanager.h"
23 #include "qgsproject.h"
24 
25 QgsJSONExporter::QgsJSONExporter( const QgsVectorLayer* vectorLayer, int precision )
26  : mPrecision( precision )
27  , mIncludeGeometry( true )
28  , mIncludeAttributes( true )
29  , mIncludeRelatedAttributes( false )
30  , mLayerId( vectorLayer ? vectorLayer->id() : QString() )
31 {
32  if ( vectorLayer )
33  {
34  mCrs = vectorLayer->crs();
35  mTransform.setSourceCrs( mCrs );
36  }
38 }
39 
41 {
42  mLayerId = vectorLayer ? vectorLayer->id() : QString();
43  if ( vectorLayer )
44  {
45  mCrs = vectorLayer->crs();
46  mTransform.setSourceCrs( mCrs );
47  }
48 }
49 
51 {
52  return qobject_cast< QgsVectorLayer* >( QgsMapLayerRegistry::instance()->mapLayer( mLayerId ) );
53 }
54 
56 {
57  mCrs = crs;
58  mTransform.setSourceCrs( mCrs );
59 }
60 
62 {
63  return mCrs;
64 }
65 
66 QString QgsJSONExporter::exportFeature( const QgsFeature& feature, const QVariantMap& extraProperties,
67  const QVariant& id ) const
68 {
69  QString s = "{\n \"type\":\"Feature\",\n";
70 
71  // ID
72  s += QString( " \"id\":%1,\n" ).arg( !id.isValid() ? QString::number( feature.id() ) : QgsJSONUtils::encodeValue( id ) );
73 
74  const QgsGeometry* geom = feature.constGeometry();
75  if ( geom && !geom->isEmpty() && mIncludeGeometry )
76  {
77  const QgsGeometry* exportGeom = geom;
78  if ( mCrs.isValid() )
79  {
80  QgsGeometry* clone = new QgsGeometry( *geom );
81  try
82  {
83  if ( clone->transform( mTransform ) == 0 )
84  exportGeom = clone;
85  else
86  delete clone;
87  }
88  catch ( QgsCsException &cse )
89  {
90  Q_UNUSED( cse );
91  delete clone;
92  }
93  }
94  QgsRectangle box = exportGeom->boundingBox();
95 
96  if ( QgsWKBTypes::flatType( exportGeom->geometry()->wkbType() ) != QgsWKBTypes::Point )
97  {
98  s += QString( " \"bbox\":[%1, %2, %3, %4],\n" ).arg( qgsDoubleToString( box.xMinimum(), mPrecision ),
99  qgsDoubleToString( box.yMinimum(), mPrecision ),
100  qgsDoubleToString( box.xMaximum(), mPrecision ),
101  qgsDoubleToString( box.yMaximum(), mPrecision ) );
102  }
103  s += " \"geometry\":\n ";
104  s += exportGeom->exportToGeoJSON( mPrecision );
105  s += ",\n";
106 
107  if ( exportGeom != geom )
108  delete exportGeom;
109  }
110  else
111  {
112  s += " \"geometry\":null,\n";
113  }
114 
115  // build up properties element
116  QString properties;
117  int attributeCounter = 0;
118  if ( mIncludeAttributes || !extraProperties.isEmpty() )
119  {
120  //read all attribute values from the feature
121 
122  if ( mIncludeAttributes )
123  {
124  const QgsFields* fields = feature.fields();
125 
126  for ( int i = 0; i < fields->count(); ++i )
127  {
128  if (( !mAttributeIndexes.isEmpty() && !mAttributeIndexes.contains( i ) ) || mExcludedAttributeIndexes.contains( i ) )
129  continue;
130 
131  if ( attributeCounter > 0 )
132  properties += ",\n";
133  QVariant val = feature.attributes().at( i );
134 
135  properties += QString( " \"%1\":%2" ).arg( fields->at( i ).name(), QgsJSONUtils::encodeValue( val ) );
136 
137  ++attributeCounter;
138  }
139  }
140 
141  if ( !extraProperties.isEmpty() )
142  {
143  QVariantMap::const_iterator it = extraProperties.constBegin();
144  for ( ; it != extraProperties.constEnd(); ++it )
145  {
146  if ( attributeCounter > 0 )
147  properties += ",\n";
148 
149  properties += QString( " \"%1\":%2" ).arg( it.key(), QgsJSONUtils::encodeValue( it.value() ) );
150 
151  ++attributeCounter;
152  }
153  }
154 
155  // related attributes
156  QgsVectorLayer* vl = vectorLayer();
157  if ( vl && mIncludeRelatedAttributes )
158  {
160  Q_FOREACH ( const QgsRelation& relation, relations )
161  {
162  if ( attributeCounter > 0 )
163  properties += ",\n";
164 
165  QgsFeatureRequest req = relation.getRelatedFeaturesRequest( feature );
167  QgsVectorLayer* childLayer = relation.referencingLayer();
168  QString relatedFeatureAttributes;
169  if ( childLayer )
170  {
171  QgsFeatureIterator it = childLayer->getFeatures( req );
172  QgsFeature relatedFet;
173  int relationFeatures = 0;
174  while ( it.nextFeature( relatedFet ) )
175  {
176  if ( relationFeatures > 0 )
177  relatedFeatureAttributes += ",\n";
178 
179  relatedFeatureAttributes += QgsJSONUtils::exportAttributes( relatedFet );
180  relationFeatures++;
181  }
182  }
183  relatedFeatureAttributes.prepend( '[' ).append( ']' );
184 
185  properties += QString( " \"%1\":%2" ).arg( relation.name(), relatedFeatureAttributes );
186  attributeCounter++;
187  }
188  }
189  }
190 
191  bool hasProperties = attributeCounter > 0;
192 
193  s += " \"properties\":";
194  if ( hasProperties )
195  {
196  //read all attribute values from the feature
197  s += "{\n" + properties + "\n }\n";
198  }
199  else
200  {
201  s += "null\n";
202  }
203 
204  s += '}';
205 
206  return s;
207 }
208 
210 {
211  QStringList featureJSON;
212  Q_FOREACH ( const QgsFeature& feature, features )
213  {
214  featureJSON << exportFeature( feature );
215  }
216 
217  return QString( "{ \"type\": \"FeatureCollection\",\n \"features\":[\n%1\n]}" ).arg( featureJSON.join( ",\n" ) );
218 }
219 
220 
221 
222 //
223 // QgsJSONUtils
224 //
225 
227 {
228  return QgsOgrUtils::stringToFeatureList( string, fields, encoding );
229 }
230 
232 {
233  return QgsOgrUtils::stringToFields( string, encoding );
234 }
235 
237 {
238  if ( value.isNull() )
239  return "null";
240 
241  switch ( value.type() )
242  {
243  case QVariant::Int:
244  case QVariant::UInt:
245  case QVariant::LongLong:
246  case QVariant::ULongLong:
247  case QVariant::Double:
248  return value.toString();
249 
250  case QVariant::Bool:
251  return value.toBool() ? "true" : "false";
252 
253  case QVariant::StringList:
254  {
255  QStringList input = value.toStringList();
256  QStringList output;
257  Q_FOREACH ( const QString& string, input )
258  {
259  output << encodeValue( string );
260  }
261  return output.join( "," ).prepend( '[' ).append( ']' );
262  }
263 
264  case QVariant::List:
265  {
266  QVariantList input = value.toList();
267  QStringList output;
268  Q_FOREACH ( const QVariant& v, input )
269  {
270  output << encodeValue( v );
271  }
272  return output.join( "," ).prepend( '[' ).append( ']' );
273  }
274 
275  case QVariant::Map:
276  {
277  QMap< QString, QVariant > input = value.toMap();
278  QStringList output;
280  for ( ; it != input.constEnd(); ++it )
281  {
282  output << encodeValue( it.key() ) + ':' + encodeValue( it.value() );
283  }
284  return output.join( ",\n" ).prepend( '{' ).append( '}' );
285  }
286 
287  default:
288  case QVariant::String:
289  QString v = value.toString()
290  .replace( '\\', "\\\\" )
291  .replace( '"', "\\\"" )
292  .replace( '\r', "\\r" )
293  .replace( '\b', "\\b" )
294  .replace( '\t', "\\t" )
295  .replace( '/', "\\/" )
296  .replace( '\n', "\\n" );
297 
298  return v.prepend( '"' ).append( '"' );
299  }
300 }
301 
303 {
304  const QgsFields* fields = feature.fields();
305  QString attrs;
306  for ( int i = 0; i < fields->count(); ++i )
307  {
308  if ( i > 0 )
309  attrs += ",\n";
310 
311  QVariant val = feature.attributes().at( i );
312  attrs += encodeValue( fields->at( i ).name() ) + ':' + encodeValue( val );
313  }
314  return attrs.prepend( '{' ).append( '}' );
315 }
316 
const_iterator constBegin() const
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
QString & append(QChar ch)
QgsAttributes attributes() const
Returns the feature&#39;s attributes.
Definition: qgsfeature.cpp:110
QString name
Definition: qgsfield.h:52
static QString exportAttributes(const QgsFeature &feature)
Exports all attributes from a QgsFeature as a JSON map type.
QgsVectorLayer * vectorLayer() const
Returns the associated vector layer, if set.
void setSourceCrs(const QgsCoordinateReferenceSystem &theCRS)
QList< QVariant > toList() const
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
QString & prepend(QChar ch)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QString exportFeatures(const QgsFeatureList &features) const
Returns a GeoJSON string representation of a list of features (feature collection).
const_iterator constBegin() const
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a GeoJSON string representing a collection of features...
Container of fields for a vector layer.
Definition: qgsfield.h:252
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
QString join(const QString &separator) const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
QgsRelationManager * relationManager() const
int count() const
Return number of items.
Definition: qgsfield.cpp:402
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:422
QString number(int n, int base)
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a string representing a collection of features using OGR.
const QgsFields * fields() const
Returns the field map associated with the feature.
Definition: qgsfeature.cpp:188
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
QgsJSONExporter(const QgsVectorLayer *vectorLayer=nullptr, int precision=6)
Constructor for QgsJSONExporter.
bool isNull() const
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:341
static QString encodeValue(const QVariant &value)
Encodes a value to a JSON string representation, adding appropriate quotations and escaping where req...
bool isEmpty() const
const_iterator constEnd() const
This class wraps a request for features to a vector layer (or directly its vector data provider)...
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
QgsFeatureRequest & setFlags(const QgsFeatureRequest::Flags &flags)
Set flags that affect how features will be fetched.
QList< QgsRelation > referencedRelations(QgsVectorLayer *layer=nullptr) const
Get all relations where this layer is the referenced part (i.e.
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a string representing a collection of features using OGR...
QgsFeatureRequest getRelatedFeaturesRequest(const QgsFeature &feature) const
Creates a request to return all the features on the referencing (child) layer which have a foreign ke...
const QgsCoordinateReferenceSystem & sourceCrs() const
Returns the source CRS for feature geometries.
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:202
bool contains(const T &value) const
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:187
const Key key(const T &value) const
void setDestCRS(const QgsCoordinateReferenceSystem &theCRS)
QString & replace(int position, int n, QChar after)
const T & at(int i) const
QgsVectorLayer * referencingLayer() const
Access the referencing (child) layer This is the layer which has the field(s) which point to another ...
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
QMap< QString, QVariant > toMap() const
QStringList toStringList() const
QString exportToGeoJSON(int precision=17) const
Exports the geometry to GeoJSON.
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
void setSourceCrs(const QgsCoordinateReferenceSystem &crs)
Sets the source CRS for feature geometries.
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
Class for storing a coordinate reference system (CRS)
bool toBool() const
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
int transform(const QgsCoordinateTransform &ct)
Transform this geometry as described by CoordinateTransform ct.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
void setVectorLayer(const QgsVectorLayer *vectorLayer)
Sets the associated vector layer (required for related attribute export).
Custom exception class for Coordinate Reference System related exceptions.
bool nextFeature(QgsFeature &f)
Type type() const
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Represents a vector layer which manages a vector based data sets.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
QString exportFeature(const QgsFeature &feature, const QVariantMap &extraProperties=QVariantMap(), const QVariant &id=QVariant()) const
Returns a GeoJSON string representation of a feature.
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a GeoJSON string to a collection of features.
QString name() const
Returns a human readable name for this relation.
const T value(const Key &key) const
bool isValid() const
Returns whether this CRS is correctly initialized and usable.