QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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 "qgsfeatureiterator.h"
18#include "qgsogrutils.h"
19#include "qgsgeometry.h"
20#include "qgsvectorlayer.h"
21#include "qgsrelation.h"
22#include "qgsrelationmanager.h"
23#include "qgsproject.h"
24#include "qgsexception.h"
25#include "qgslogger.h"
27#include "qgsfieldformatter.h"
28#include "qgsapplication.h"
29#include "qgsfeatureid.h"
30
31#include <QJsonDocument>
32#include <QJsonArray>
33#include <QTextCodec>
34#include <nlohmann/json.hpp>
35
37 : mPrecision( precision )
38 , mLayer( vectorLayer )
39{
40 if ( vectorLayer )
41 {
42 mCrs = vectorLayer->crs();
43 mTransform.setSourceCrs( mCrs );
44 }
45 mTransform.setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
46}
47
49{
50 mLayer = vectorLayer;
51 if ( vectorLayer )
52 {
53 mCrs = vectorLayer->crs();
54 mTransform.setSourceCrs( mCrs );
55 }
56}
57
59{
60 return mLayer.data();
61}
62
64{
65 mCrs = crs;
66 mTransform.setSourceCrs( mCrs );
67}
68
70{
71 return mCrs;
72}
73
74QString QgsJsonExporter::exportFeature( const QgsFeature &feature, const QVariantMap &extraProperties,
75 const QVariant &id, int indent ) const
76{
77 return QString::fromStdString( exportFeatureToJsonObject( feature, extraProperties, id ).dump( indent ) );
78}
79
80json QgsJsonExporter::exportFeatureToJsonObject( const QgsFeature &feature, const QVariantMap &extraProperties, const QVariant &id ) const
81{
82 json featureJson
83 {
84 { "type", "Feature" },
85 };
86 if ( id.isValid() )
87 {
88 bool ok = false;
89 auto intId = id.toLongLong( &ok );
90 if ( ok )
91 {
92 featureJson["id"] = intId;
93 }
94 else
95 {
96 featureJson["id"] = id.toString().toStdString();
97 }
98 }
99 else if ( FID_IS_NULL( feature.id() ) )
100 {
101 featureJson["id"] = nullptr;
102 }
103 else
104 {
105 featureJson["id"] = feature.id();
106 }
107
108 QgsGeometry geom = feature.geometry();
109 if ( !geom.isNull() && mIncludeGeometry )
110 {
111 if ( mCrs.isValid() )
112 {
113 try
114 {
115 QgsGeometry transformed = geom;
116 if ( mTransformGeometries && transformed.transform( mTransform ) == Qgis::GeometryOperationResult::Success )
117 geom = transformed;
118 }
119 catch ( QgsCsException &cse )
120 {
121 Q_UNUSED( cse )
122 }
123 }
124 QgsRectangle box = geom.boundingBox();
125
127 {
128 featureJson[ "bbox" ] =
129 {
130 qgsRound( box.xMinimum(), mPrecision ),
131 qgsRound( box.yMinimum(), mPrecision ),
132 qgsRound( box.xMaximum(), mPrecision ),
133 qgsRound( box.yMaximum(), mPrecision )
134 };
135 }
136 featureJson[ "geometry" ] = geom.asJsonObject( mPrecision );
137 }
138 else
139 {
140 featureJson[ "geometry" ] = nullptr;
141 }
142
143 // build up properties element
144 int attributeCounter { 0 };
145 json properties;
146 if ( mIncludeAttributes || !extraProperties.isEmpty() )
147 {
148 //read all attribute values from the feature
149 if ( mIncludeAttributes )
150 {
151 QgsFields fields = mLayer ? mLayer->fields() : feature.fields();
152 // List of formatters through we want to pass the values
153 QStringList formattersAllowList;
154 formattersAllowList << QStringLiteral( "KeyValue" )
155 << QStringLiteral( "List" )
156 << QStringLiteral( "ValueRelation" )
157 << QStringLiteral( "ValueMap" );
158
159 for ( int i = 0; i < fields.count(); ++i )
160 {
161 if ( ( !mAttributeIndexes.isEmpty() && !mAttributeIndexes.contains( i ) ) || mExcludedAttributeIndexes.contains( i ) )
162 continue;
163
164 QVariant val = feature.attributes().at( i );
165
166 if ( mLayer )
167 {
168 const QgsEditorWidgetSetup setup = fields.at( i ).editorWidgetSetup();
170 if ( formattersAllowList.contains( fieldFormatter->id() ) )
171 val = fieldFormatter->representValue( mLayer.data(), i, setup.config(), QVariant(), val );
172 }
173
174 QString name = fields.at( i ).name();
175 if ( mAttributeDisplayName )
176 {
177 name = mLayer->attributeDisplayName( i );
178 }
179 properties[ name.toStdString() ] = QgsJsonUtils::jsonFromVariant( val );
180 attributeCounter++;
181 }
182 }
183
184 if ( !extraProperties.isEmpty() )
185 {
186 QVariantMap::const_iterator it = extraProperties.constBegin();
187 for ( ; it != extraProperties.constEnd(); ++it )
188 {
189 properties[ it.key().toStdString() ] = QgsJsonUtils::jsonFromVariant( it.value() );
190 attributeCounter++;
191 }
192 }
193
194 // related attributes
195 if ( mLayer && mIncludeRelatedAttributes )
196 {
197 QList< QgsRelation > relations = QgsProject::instance()->relationManager()->referencedRelations( mLayer.data() );
198 for ( const auto &relation : std::as_const( relations ) )
199 {
200 QgsFeatureRequest req = relation.getRelatedFeaturesRequest( feature );
202 QgsVectorLayer *childLayer = relation.referencingLayer();
203 json relatedFeatureAttributes;
204 if ( childLayer )
205 {
206 QgsFeatureIterator it = childLayer->getFeatures( req );
207 QVector<QVariant> attributeWidgetCaches;
208 int fieldIndex = 0;
209 const QgsFields fields { childLayer->fields() };
210 for ( const QgsField &field : fields )
211 {
214 attributeWidgetCaches.append( fieldFormatter->createCache( childLayer, fieldIndex, setup.config() ) );
215 fieldIndex++;
216 }
217 QgsFeature relatedFet;
218 while ( it.nextFeature( relatedFet ) )
219 {
220 relatedFeatureAttributes += QgsJsonUtils::exportAttributesToJsonObject( relatedFet, childLayer, attributeWidgetCaches );
221 }
222 }
223 properties[ relation.name().toStdString() ] = relatedFeatureAttributes;
224 attributeCounter++;
225 }
226 }
227 }
228 featureJson[ "properties" ] = properties;
229 return featureJson;
230}
231
232QString QgsJsonExporter::exportFeatures( const QgsFeatureList &features, int indent ) const
233{
234 return QString::fromStdString( exportFeaturesToJsonObject( features ).dump( indent ) );
235}
236
238{
239 json data
240 {
241 { "type", "FeatureCollection" },
242 { "features", json::array() }
243 };
244 for ( const QgsFeature &feature : std::as_const( features ) )
245 {
246 data["features"].push_back( exportFeatureToJsonObject( feature ) );
247 }
248 return data;
249}
250
251//
252// QgsJsonUtils
253//
254
255QgsFeatureList QgsJsonUtils::stringToFeatureList( const QString &string, const QgsFields &fields, QTextCodec *encoding )
256{
257 if ( !encoding )
258 encoding = QTextCodec::codecForName( "UTF-8" );
259
260 return QgsOgrUtils::stringToFeatureList( string, fields, encoding );
261}
262
263QgsFields QgsJsonUtils::stringToFields( const QString &string, QTextCodec *encoding )
264{
265 if ( !encoding )
266 encoding = QTextCodec::codecForName( "UTF-8" );
267
268 return QgsOgrUtils::stringToFields( string, encoding );
269}
270
271QString QgsJsonUtils::encodeValue( const QVariant &value )
272{
273 if ( QgsVariantUtils::isNull( value ) )
274 return QStringLiteral( "null" );
275
276 switch ( value.type() )
277 {
278 case QVariant::Int:
279 case QVariant::UInt:
280 case QVariant::LongLong:
281 case QVariant::ULongLong:
282 case QVariant::Double:
283 return value.toString();
284
285 case QVariant::Bool:
286 return value.toBool() ? "true" : "false";
287
288 case QVariant::StringList:
289 case QVariant::List:
290 case QVariant::Map:
291 return QString::fromUtf8( QJsonDocument::fromVariant( value ).toJson( QJsonDocument::Compact ) );
292
293 default:
294 case QVariant::String:
295 QString v = value.toString()
296 .replace( '\\', QLatin1String( "\\\\" ) )
297 .replace( '"', QLatin1String( "\\\"" ) )
298 .replace( '\r', QLatin1String( "\\r" ) )
299 .replace( '\b', QLatin1String( "\\b" ) )
300 .replace( '\t', QLatin1String( "\\t" ) )
301 .replace( '/', QLatin1String( "\\/" ) )
302 .replace( '\n', QLatin1String( "\\n" ) );
303
304 return v.prepend( '"' ).append( '"' );
305 }
306}
307
308QString QgsJsonUtils::exportAttributes( const QgsFeature &feature, QgsVectorLayer *layer, const QVector<QVariant> &attributeWidgetCaches )
309{
310 QgsFields fields = feature.fields();
311 QString attrs;
312 for ( int i = 0; i < fields.count(); ++i )
313 {
314 if ( i > 0 )
315 attrs += QLatin1String( ",\n" );
316
317 QVariant val = feature.attributes().at( i );
318
319 if ( layer )
320 {
321 QgsEditorWidgetSetup setup = layer->fields().at( i ).editorWidgetSetup();
323 if ( fieldFormatter != QgsApplication::fieldFormatterRegistry()->fallbackFieldFormatter() )
324 val = fieldFormatter->representValue( layer, i, setup.config(), attributeWidgetCaches.count() >= i ? attributeWidgetCaches.at( i ) : QVariant(), val );
325 }
326
327 attrs += encodeValue( fields.at( i ).name() ) + ':' + encodeValue( val );
328 }
329 return attrs.prepend( '{' ).append( '}' );
330}
331
332QVariantList QgsJsonUtils::parseArray( const QString &json, QVariant::Type type )
333{
334 QString errorMessage;
335 QVariantList result;
336 try
337 {
338 const auto jObj( json::parse( json.toStdString() ) );
339 if ( ! jObj.is_array() )
340 {
341 throw json::parse_error::create( 0, 0, QStringLiteral( "JSON value must be an array" ).toStdString() );
342 }
343 for ( const auto &item : jObj )
344 {
345 // Create a QVariant from the array item
346 QVariant v;
347 if ( item.is_number_integer() )
348 {
349 v = item.get<int>();
350 }
351 else if ( item.is_number_unsigned() )
352 {
353 v = item.get<unsigned>();
354 }
355 else if ( item.is_number_float() )
356 {
357 // Note: it's a double and not a float on purpose
358 v = item.get<double>();
359 }
360 else if ( item.is_string() )
361 {
362 v = QString::fromStdString( item.get<std::string>() );
363 }
364 else if ( item.is_boolean() )
365 {
366 v = item.get<bool>();
367 }
368 else if ( item.is_null() )
369 {
370 // Fallback to int
371 v = QVariant( type == QVariant::Type::Invalid ? QVariant::Type::Int : type );
372 }
373
374 // If a destination type was specified (it's not invalid), try to convert
375 if ( type != QVariant::Invalid )
376 {
377 if ( ! v.convert( static_cast<int>( type ) ) )
378 {
379 QgsLogger::warning( QStringLiteral( "Cannot convert json array element to specified type, ignoring: %1" ).arg( v.toString() ) );
380 }
381 else
382 {
383 result.push_back( v );
384 }
385 }
386 else
387 {
388 result.push_back( v );
389 }
390 }
391 }
392 catch ( json::parse_error &ex )
393 {
394 errorMessage = ex.what();
395 QgsLogger::warning( QStringLiteral( "Cannot parse json (%1): %2" ).arg( ex.what(), json ) );
396 }
397
398 return result;
399}
400
401json QgsJsonUtils::jsonFromVariant( const QVariant &val )
402{
403 if ( QgsVariantUtils::isNull( val ) )
404 {
405 return nullptr;
406 }
407 json j;
408 if ( val.type() == QVariant::Type::Map )
409 {
410 const QVariantMap &vMap = val.toMap();
411 json jMap = json::object();
412 for ( auto it = vMap.constBegin(); it != vMap.constEnd(); it++ )
413 {
414 jMap[ it.key().toStdString() ] = jsonFromVariant( it.value() );
415 }
416 j = jMap;
417 }
418 else if ( val.type() == QVariant::Type::List || val.type() == QVariant::Type::StringList )
419 {
420 const QVariantList &vList = val.toList();
421 json jList = json::array();
422 for ( const auto &v : vList )
423 {
424 jList.push_back( jsonFromVariant( v ) );
425 }
426 j = jList;
427 }
428 else
429 {
430 switch ( val.userType() )
431 {
432 case QMetaType::Int:
433 case QMetaType::UInt:
434 case QMetaType::LongLong:
435 case QMetaType::ULongLong:
436 j = val.toLongLong();
437 break;
438 case QMetaType::Double:
439 case QMetaType::Float:
440 j = val.toDouble();
441 break;
442 case QMetaType::Bool:
443 j = val.toBool();
444 break;
445 case QMetaType::QByteArray:
446 j = val.toByteArray().toBase64().toStdString();
447 break;
448 default:
449 j = val.toString().toStdString();
450 break;
451 }
452 }
453 return j;
454}
455
456QVariant QgsJsonUtils::parseJson( const std::string &jsonString )
457{
458 QString error;
459 const QVariant res = parseJson( jsonString, error );
460
461 if ( !error.isEmpty() )
462 {
463 QgsLogger::warning( QStringLiteral( "Cannot parse json (%1): %2" ).arg( error,
464 QString::fromStdString( jsonString ) ) );
465 }
466 return res;
467}
468
469QVariant QgsJsonUtils::parseJson( const std::string &jsonString, QString &error )
470{
471 // tracks whether entire json string is a primitive
472 bool isPrimitive = true;
473
474 std::function<QVariant( json )> _parser { [ & ]( json jObj ) -> QVariant {
475 QVariant result;
476 if ( jObj.is_array() )
477 {
478 isPrimitive = false;
479 QVariantList results;
480 results.reserve( jObj.size() );
481 for ( const auto &item : jObj )
482 {
483 results.push_back( _parser( item ) );
484 }
485 result = results;
486 }
487 else if ( jObj.is_object() )
488 {
489 isPrimitive = false;
490 QVariantMap results;
491 for ( const auto &item : jObj.items() )
492 {
493 const auto key { QString::fromStdString( item.key() ) };
494 const auto value { _parser( item.value() ) };
495 results[ key ] = value;
496 }
497 result = results;
498 }
499 else
500 {
501 if ( jObj.is_number_integer() )
502 {
503 result = jObj.get<int>();
504 }
505 else if ( jObj.is_number_unsigned() )
506 {
507 result = jObj.get<unsigned>();
508 }
509 else if ( jObj.is_boolean() )
510 {
511 result = jObj.get<bool>();
512 }
513 else if ( jObj.is_number_float() )
514 {
515 // Note: it's a double and not a float on purpose
516 result = jObj.get<double>();
517 }
518 else if ( jObj.is_string() )
519 {
520 if ( isPrimitive && jObj.get<std::string>().length() == 0 )
521 {
522 result = QString::fromStdString( jObj.get<std::string>() ).append( "\"" ).insert( 0, "\"" );
523 }
524 else
525 {
526 result = QString::fromStdString( jObj.get<std::string>() );
527 }
528 }
529 else if ( jObj.is_null() )
530 {
531 // Do nothing (leave invalid)
532 }
533 }
534 return result;
535 }
536 };
537
538 error.clear();
539 try
540 {
541 const json j = json::parse( jsonString );
542 return _parser( j );
543 }
544 catch ( json::parse_error &ex )
545 {
546 error = QString::fromStdString( ex.what() );
547 }
548 return QVariant();
549}
550
551QVariant QgsJsonUtils::parseJson( const QString &jsonString )
552{
553 return parseJson( jsonString.toStdString() );
554}
555
556json QgsJsonUtils::exportAttributesToJsonObject( const QgsFeature &feature, QgsVectorLayer *layer, const QVector<QVariant> &attributeWidgetCaches )
557{
558 QgsFields fields = feature.fields();
559 json attrs;
560 for ( int i = 0; i < fields.count(); ++i )
561 {
562 QVariant val = feature.attributes().at( i );
563
564 if ( layer )
565 {
566 QgsEditorWidgetSetup setup = layer->fields().at( i ).editorWidgetSetup();
568 if ( fieldFormatter != QgsApplication::fieldFormatterRegistry()->fallbackFieldFormatter() )
569 val = fieldFormatter->representValue( layer, i, setup.config(), attributeWidgetCaches.count() >= i ? attributeWidgetCaches.at( i ) : QVariant(), val );
570 }
571 attrs[fields.at( i ).name().toStdString()] = jsonFromVariant( val );
572 }
573 return attrs;
574}
@ Success
Operation succeeded.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs)
Sets the source coordinate reference system.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination coordinate reference system.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
Holder for the widget type and its configuration for a field.
QVariantMap config() const
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsFields fields
Definition: qgsfeature.h:66
QgsGeometry geometry
Definition: qgsfeature.h:67
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
QgsFieldFormatter * fieldFormatter(const QString &id) const
Gets a field formatter by its id.
A field formatter helps to handle and display values for a field.
virtual QVariant createCache(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config) const
Create a cache for a given field.
virtual QString id() const =0
Returns a unique id for this field formatter.
virtual QString representValue(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value) const
Create a pretty String representation of the value.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QString name
Definition: qgsfield.h:60
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition: qgsfield.cpp:631
Container of fields for a vector layer.
Definition: qgsfields.h:45
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Q_GADGET bool isNull
Definition: qgsgeometry.h:166
virtual json asJsonObject(int precision=17) const
Exports the geometry to a json object.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
json exportFeatureToJsonObject(const QgsFeature &feature, const QVariantMap &extraProperties=QVariantMap(), const QVariant &id=QVariant()) const
Returns a QJsonObject representation of a feature.
json exportFeaturesToJsonObject(const QgsFeatureList &features) const
Returns a JSON object representation of a list of features (feature collection).
void setSourceCrs(const QgsCoordinateReferenceSystem &crs)
Sets the source CRS for feature geometries.
QgsVectorLayer * vectorLayer() const
Returns the associated vector layer, if set.
QString exportFeature(const QgsFeature &feature, const QVariantMap &extraProperties=QVariantMap(), const QVariant &id=QVariant(), int indent=-1) const
Returns a GeoJSON string representation of a feature.
QString exportFeatures(const QgsFeatureList &features, int indent=-1) const
Returns a GeoJSON string representation of a list of features (feature collection).
void setVectorLayer(QgsVectorLayer *vectorLayer)
Sets the associated vector layer (required for related attribute export).
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source CRS for feature geometries.
QgsJsonExporter(QgsVectorLayer *vectorLayer=nullptr, int precision=6)
Constructor for QgsJsonExporter.
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields=QgsFields(), QTextCodec *encoding=nullptr)
Attempts to parse a GeoJSON string to a collection of features.
static QString exportAttributes(const QgsFeature &feature, QgsVectorLayer *layer=nullptr, const QVector< QVariant > &attributeWidgetCaches=QVector< QVariant >())
Exports all attributes from a QgsFeature as a JSON map type.
static Q_INVOKABLE QString encodeValue(const QVariant &value)
Encodes a value to a JSON string representation, adding appropriate quotations and escaping where req...
static QVariant parseJson(const std::string &jsonString)
Converts JSON jsonString to a QVariant, in case of parsing error an invalid QVariant is returned and ...
static json exportAttributesToJsonObject(const QgsFeature &feature, QgsVectorLayer *layer=nullptr, const QVector< QVariant > &attributeWidgetCaches=QVector< QVariant >())
Exports all attributes from a QgsFeature as a json object.
static QgsFields stringToFields(const QString &string, QTextCodec *encoding=nullptr)
Attempts to retrieve the fields from a GeoJSON string representing a collection of features.
static Q_INVOKABLE QVariantList parseArray(const QString &json, QVariant::Type type=QVariant::Invalid)
Parse a simple array (depth=1)
static json jsonFromVariant(const QVariant &v)
Converts a QVariant v to a json object.
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a string representing a collection of features using OGR.
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a string representing a collection of features using OGR.
QgsRelationManager * relationManager
Definition: qgsproject.h:114
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
Definition: qgis.h:2581
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:922
#define FID_IS_NULL(fid)
Definition: qgsfeatureid.h:30
const QgsField & field
Definition: qgsfield.h:463
QgsSQLStatement::Node * parse(const QString &str, QString &parserErrorMsg, bool allowFragments)
const QgsCoordinateReferenceSystem & crs
int precision