31#include <QJsonDocument>
34#include <nlohmann/json.hpp>
38 , mLayer( vectorLayer )
78 const QVariant &
id,
int indent )
const
87 {
"type",
"Feature" },
92 auto intId =
id.toLongLong( &ok );
95 featureJson[
"id"] = intId;
99 featureJson[
"id"] =
id.toString().toStdString();
104 featureJson[
"id"] =
nullptr;
108 featureJson[
"id"] = feature.
id();
112 if ( !geom.
isNull() && mIncludeGeometry )
131 featureJson[
"bbox" ] =
139 featureJson[
"geometry" ] = geom.
asJsonObject( mPrecision );
143 featureJson[
"geometry" ] =
nullptr;
147 int attributeCounter { 0 };
149 if ( mIncludeAttributes || !extraProperties.isEmpty() )
152 if ( mIncludeAttributes )
156 QStringList formattersAllowList;
157 formattersAllowList << QStringLiteral(
"KeyValue" )
158 << QStringLiteral(
"List" )
159 << QStringLiteral(
"ValueRelation" )
160 << QStringLiteral(
"ValueMap" );
162 for (
int i = 0; i < fields.
count(); ++i )
164 if ( ( !mAttributeIndexes.isEmpty() && !mAttributeIndexes.contains( i ) ) || mExcludedAttributeIndexes.contains( i ) )
173 if ( formattersAllowList.contains( fieldFormatter->
id() ) )
177 QString name = fields.
at( i ).
name();
178 if ( mAttributeDisplayName )
180 name = mLayer->attributeDisplayName( i );
187 if ( !extraProperties.isEmpty() )
189 QVariantMap::const_iterator it = extraProperties.constBegin();
190 for ( ; it != extraProperties.constEnd(); ++it )
198 if ( mLayer && mIncludeRelatedAttributes )
201 for (
const auto &relation : std::as_const( relations ) )
206 json relatedFeatureAttributes;
210 QVector<QVariant> attributeWidgetCaches;
217 attributeWidgetCaches.append( fieldFormatter->
createCache( childLayer, fieldIndex, setup.
config() ) );
226 properties[ relation.name().toStdString() ] = relatedFeatureAttributes;
231 featureJson[
"properties" ] = properties;
244 {
"type",
"FeatureCollection" },
245 {
"features", json::array() }
247 for (
const QgsFeature &feature : std::as_const( features ) )
256 mDestinationCrs = destinationCrs;
267 encoding = QTextCodec::codecForName(
"UTF-8" );
275 encoding = QTextCodec::codecForName(
"UTF-8" );
283 return QStringLiteral(
"null" );
285 switch ( value.type() )
289 case QVariant::LongLong:
290 case QVariant::ULongLong:
291 case QVariant::Double:
292 return value.toString();
295 return value.toBool() ?
"true" :
"false";
297 case QVariant::StringList:
300 return QString::fromUtf8( QJsonDocument::fromVariant( value ).toJson( QJsonDocument::Compact ) );
303 case QVariant::String:
304 QString v = value.toString()
305 .replace(
'\\', QLatin1String(
"\\\\" ) )
306 .replace(
'"', QLatin1String(
"\\\"" ) )
307 .replace(
'\r', QLatin1String(
"\\r" ) )
308 .replace(
'\b', QLatin1String(
"\\b" ) )
309 .replace(
'\t', QLatin1String(
"\\t" ) )
310 .replace(
'/', QLatin1String(
"\\/" ) )
311 .replace(
'\n', QLatin1String(
"\\n" ) );
313 return v.prepend(
'"' ).append(
'"' );
321 for (
int i = 0; i < fields.
count(); ++i )
324 attrs += QLatin1String(
",\n" );
333 val = fieldFormatter->
representValue( layer, i, setup.
config(), attributeWidgetCaches.count() >= i ? attributeWidgetCaches.at( i ) : QVariant(), val );
338 return attrs.prepend(
'{' ).append(
'}' );
343 QString errorMessage;
347 const auto jObj(
json::parse( json.toStdString() ) );
348 if ( ! jObj.is_array() )
350 throw json::parse_error::create( 0, 0, QStringLiteral(
"JSON value must be an array" ).toStdString() );
352 for (
const auto &item : jObj )
356 if ( item.is_number_integer() )
360 else if ( item.is_number_unsigned() )
362 v = item.get<
unsigned>();
364 else if ( item.is_number_float() )
367 v = item.get<
double>();
369 else if ( item.is_string() )
371 v = QString::fromStdString( item.get<std::string>() );
373 else if ( item.is_boolean() )
375 v = item.get<
bool>();
377 else if ( item.is_null() )
380 v = QVariant( type == QVariant::Type::Invalid ? QVariant::Type::Int : type );
384 if ( type != QVariant::Invalid )
386 if ( ! v.convert(
static_cast<int>( type ) ) )
388 QgsLogger::warning( QStringLiteral(
"Cannot convert json array element to specified type, ignoring: %1" ).arg( v.toString() ) );
392 result.push_back( v );
397 result.push_back( v );
401 catch ( json::parse_error &ex )
403 errorMessage = ex.what();
404 QgsLogger::warning( QStringLiteral(
"Cannot parse json (%1): %2" ).arg( ex.what(), json ) );
417 if ( val.type() == QVariant::Type::Map )
419 const QVariantMap &vMap = val.toMap();
420 json jMap = json::object();
421 for (
auto it = vMap.constBegin(); it != vMap.constEnd(); it++ )
427 else if ( val.type() == QVariant::Type::List || val.type() == QVariant::Type::StringList )
429 const QVariantList &vList = val.toList();
430 json jList = json::array();
431 for (
const auto &v : vList )
439 switch ( val.userType() )
442 case QMetaType::UInt:
443 case QMetaType::LongLong:
444 case QMetaType::ULongLong:
445 j = val.toLongLong();
447 case QMetaType::Double:
448 case QMetaType::Float:
451 case QMetaType::Bool:
454 case QMetaType::QByteArray:
455 j = val.toByteArray().toBase64().toStdString();
458 j = val.toString().toStdString();
468 const QVariant res =
parseJson( jsonString, error );
470 if ( !error.isEmpty() )
473 QString::fromStdString( jsonString ) ) );
481 bool isPrimitive =
true;
483 std::function<QVariant( json )> _parser { [ & ]( json jObj ) -> QVariant {
485 if ( jObj.is_array() )
488 QVariantList results;
489 results.reserve( jObj.size() );
490 for (
const auto &item : jObj )
492 results.push_back( _parser( item ) );
496 else if ( jObj.is_object() )
500 for (
const auto &item : jObj.items() )
502 const auto key { QString::fromStdString( item.key() ) };
503 const auto value { _parser( item.value() ) };
504 results[ key ] = value;
510 if ( jObj.is_number_integer() )
512 result = jObj.get<
int>();
514 else if ( jObj.is_number_unsigned() )
516 result = jObj.get<
unsigned>();
518 else if ( jObj.is_boolean() )
520 result = jObj.get<
bool>();
522 else if ( jObj.is_number_float() )
525 result = jObj.get<
double>();
527 else if ( jObj.is_string() )
529 if ( isPrimitive && jObj.get<std::string>().length() == 0 )
531 result = QString::fromStdString( jObj.get<std::string>() ).append(
"\"" ).insert( 0,
"\"" );
535 result = QString::fromStdString( jObj.get<std::string>() );
538 else if ( jObj.is_null() )
553 catch ( json::parse_error &ex )
555 error = QString::fromStdString( ex.what() );
562 return parseJson( jsonString.toStdString() );
569 for (
int i = 0; i < fields.
count(); ++i )
578 val = fieldFormatter->
representValue( layer, i, setup.
config(), attributeWidgetCaches.count() >= i ? attributeWidgetCaches.at( i ) : QVariant(), val );
@ 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.
Custom exception class for Coordinate Reference System related exceptions.
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...
Encapsulate a field in an attribute table or data source.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
int count() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
A geometry is the spatial representation of a feature.
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.
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
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.
void setDestinationCrs(const QgsCoordinateReferenceSystem &destinationCrs)
Set the destination CRS for feature geometry transformation to destinationCrs, this defaults to EPSG:...
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.
QgsCoordinateReferenceSystem crs
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
static QgsProject * instance()
Returns the QgsProject singleton instance.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
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 Qgis::WkbType flatType(Qgis::WkbType type) SIP_HOLDGIL
Returns the flat type for a WKB type.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
QList< QgsFeature > QgsFeatureList
QgsSQLStatement::Node * parse(const QString &str, QString &parserErrorMsg, bool allowFragments)
const QgsCoordinateReferenceSystem & crs