18#include <nlohmann/json.hpp>
45#include <QJsonDocument>
49#include "moc_qgsjsonutils.cpp"
51using namespace Qt::StringLiterals;
60 mTransform.setSourceCrs( mCrs );
65 mTransform.setDestinationCrs( mDestinationCrs );
74 mTransform.setSourceCrs( mCrs );
86 mTransform.setSourceCrs( mCrs );
100 catch ( json::type_error &ex )
105 catch ( json::other_error &ex )
118 const bool destinationCrsIsRfc7946Compliant = mDestinationCrs.authid() ==
"OGC:CRS84" || mDestinationCrs.authid() ==
"EPSG:4326" || mDestinationCrs.authid() ==
"CRS:84";
119 const bool sourceCrsIsRfc7946Compliant = ( mCrs.authid() ==
"OGC:CRS84" || mCrs.authid() ==
"CRS:84" || mCrs.authid() ==
"EPSG:4326" );
122 || ( mTransformGeometries && destinationCrsIsRfc7946Compliant );
125 const bool geomRequiresTransformToDestinationCrs = mCrs != mDestinationCrs;
129 const bool includeGeometryInformation { !geom.
isNull() && mIncludeGeometry };
132 const bool mainGeometryIsRfc7946Compliant {
134 && destinationCrsIsRfc7946Compliant
139 {
"type",
"Feature" },
144 featureJson[
"conformsTo"] = {
"http://www.opengis.net/spec/json-fg-1/1.0/conf/core" };
145 if ( includeGeometryInformation )
149 featureJson[
"conformsTo"].push_back(
"http://www.opengis.net/spec/json-fg-1/1.0/conf/measures" );
150 featureJson[
"measures"] = { {
"enabled",
true } };
157 if ( !extraMembers.isEmpty() )
159 QVariantMap::const_iterator it = extraMembers.constBegin();
160 for ( ; it != extraMembers.constEnd(); ++it )
169 auto intId =
id.toLongLong( &ok );
172 featureJson[
"id"] = intId;
176 featureJson[
"id"] =
id.toString().toStdString();
181 featureJson[
"id"] =
nullptr;
185 featureJson[
"id"] = feature.
id();
191 if ( includeGeometryInformation )
196 if ( requiresCRS84geom )
198 if ( sourceCrsIsRfc7946Compliant )
200 transformedCRS84Geom = geom;
206 transformedCRS84Geom.
transform( transformToCRS84 );
218 if ( destinationCrsIsRfc7946Compliant )
220 geom = transformedCRS84Geom;
222 else if ( mCrs.isValid() )
236 std::function<void( json & )> invertCoords;
237 invertCoords = [&invertCoords]( json &geometry ) {
238 if ( geometry.contains(
"coordinates" ) )
240 invertCoords( geometry[
"coordinates"] );
242 else if ( geometry.contains(
"geometries" ) )
244 for ( json &geom : geometry[
"geometries"] )
246 invertCoords( geom );
249 else if ( geometry.is_array() && geometry.size() > 0 )
251 if ( geometry[0].is_array() )
253 for ( json &geom : geometry )
255 invertCoords( geom );
260 if ( geometry.size() >= 2 && geometry[0].is_number() && geometry[1].is_number() )
262 std::swap( geometry[0], geometry[1] );
268 auto addBbox = [&featureJson, &flatType,
this](
const QgsGeometry &geometry ) {
274 auto bbox = geometry.boundingBox();
276 = {
qgsRound( bbox.xMinimum(), this->mPrecision ),
qgsRound( bbox.yMinimum(), this->mPrecision ),
qgsRound( bbox.xMaximum(), this->mPrecision ),
qgsRound( bbox.yMaximum(), this->mPrecision ) };
279 switch ( mGeoJsonProfile )
284 addBbox( transformedCRS84Geom );
302 addBbox( transformedCRS84Geom );
303 if ( !mainGeometryIsRfc7946Compliant )
305 json place = geom.
asJsonObject( mPrecision, mGeoJsonProfile );
306 if ( mDestinationCrs.hasAxisInverted() )
308 invertCoords( place );
310 featureJson[
"place"] = place;
319 if ( !mainGeometryIsRfc7946Compliant )
321 json place = geom.
asJsonObject( mPrecision, mGeoJsonProfile );
322 if ( mDestinationCrs.hasAxisInverted() )
324 invertCoords( place );
326 featureJson[
"place"] = place;
330 featureJson[
"geometry"] = geom.
asJsonObject( mPrecision, mGeoJsonProfile );
338 featureJson[
"geometry"] =
nullptr;
343 if ( mIncludeAttributes || !extraProperties.isEmpty() )
346 if ( mIncludeAttributes )
350 QStringList formattersAllowList;
351 formattersAllowList << u
"KeyValue"_s << u
"List"_s << u
"ValueRelation"_s << u
"ValueMap"_s;
353 for (
int i = 0; i < fields.
count(); ++i )
355 if ( ( !mAttributeIndexes.isEmpty() && !mAttributeIndexes.contains( i ) ) || mExcludedAttributeIndexes.contains( i ) )
360 if ( mUseFieldFormatters && mLayer )
364 if ( formattersAllowList.contains( fieldFormatter->
id() ) )
368 QString name = fields.
at( i ).
name();
369 if ( mAttributeDisplayName )
371 name = mLayer->attributeDisplayName( i );
377 if ( !extraProperties.isEmpty() )
379 QVariantMap::const_iterator it = extraProperties.constBegin();
380 for ( ; it != extraProperties.constEnd(); ++it )
387 if ( mLayer && mIncludeRelatedAttributes )
389 QList< QgsRelation > relations;
391 if (
QgsProject *project = mLayer->project() )
393 relations = project->relationManager()->referencedRelations( mLayer.data() );
396 for (
const auto &relation : std::as_const( relations ) )
401 json relatedFeatureAttributes;
405 QVector<QVariant> attributeWidgetCaches;
408 for (
const QgsField &field : fields )
412 attributeWidgetCaches.append( fieldFormatter->
createCache( childLayer, fieldIndex, setup.
config() ) );
421 properties[relation.name().toStdString()] = relatedFeatureAttributes;
425 featureJson[
"properties"] = properties;
437 json data { {
"type",
"FeatureCollection" }, {
"features", json::array() } };
438 const bool omitCollectionLevelInformation = mOmitCollectionLevelInformation;
439 mOmitCollectionLevelInformation =
true;
440 switch ( mGeoJsonProfile )
454 json conformsTo = json::array( { {
"http://www.opengis.net/spec/json-fg-1/1.0/conf/core" } } );
456 bool hasCircularArcs =
false;
457 bool hasMeasure =
false;
464 hasCircularArcs =
true;
472 if ( hasCircularArcs )
474 conformsTo.push_back( {
"http://www.opengis.net/spec/json-fg-1/1.0/conf/circular-arcs" } );
478 conformsTo.push_back( {
"http://www.opengis.net/spec/json-fg-1/1.0/conf/measures" } );
479 data[
"measures"] = { {
"enabled",
true } };
481 data[
"conformsTo"] = conformsTo;
485 mOmitCollectionLevelInformation = omitCollectionLevelInformation;
491 mDestinationCrs = destinationCrs;
492 mTransform.setDestinationCrs( mDestinationCrs );
497 return mGeoJsonProfile;
502 mGeoJsonProfile = profile;
512 encoding = QTextCodec::codecForName(
"UTF-8" );
520 encoding = QTextCodec::codecForName(
"UTF-8" );
530 switch ( value.userType() )
532 case QMetaType::Type::Int:
533 case QMetaType::Type::UInt:
534 case QMetaType::Type::LongLong:
535 case QMetaType::Type::ULongLong:
536 case QMetaType::Type::Double:
537 return value.toString();
539 case QMetaType::Type::Bool:
540 return value.toBool() ?
"true" :
"false";
542 case QMetaType::Type::QStringList:
543 case QMetaType::Type::QVariantList:
544 case QMetaType::Type::QVariantMap:
545 return QString::fromUtf8( QJsonDocument::fromVariant( value ).toJson( QJsonDocument::Compact ) );
548 case QMetaType::Type::QString:
550 = value.toString().replace(
'\\',
"\\\\"_L1 ).replace(
'"',
"\\\""_L1 ).replace(
'\r',
"\\r"_L1 ).replace(
'\b',
"\\b"_L1 ).replace(
'\t',
"\\t"_L1 ).replace(
'/',
"\\/"_L1 ).replace(
'\n',
"\\n"_L1 );
552 return v.prepend(
'"' ).append(
'"' );
560 for (
int i = 0; i < fields.
count(); ++i )
572 val = fieldFormatter->
representValue( layer, i, setup.
config(), attributeWidgetCaches.count() >= i ? attributeWidgetCaches.at( i ) : QVariant(), val );
577 return attrs.prepend(
'{' ).
append(
'}' );
582 QString errorMessage;
586 const auto jObj( json::parse( json.toStdString() ) );
587 if ( !jObj.is_array() )
589 throw json::parse_error::create( 0, 0, u
"JSON value must be an array"_s.toStdString(), &jObj );
591 for (
const auto &item : jObj )
595 if ( item.is_number_integer() )
599 else if ( item.is_number_unsigned() )
601 v = item.get<
unsigned>();
603 else if ( item.is_number_float() )
606 v = item.get<
double>();
608 else if ( item.is_string() )
610 v = QString::fromStdString( item.get<std::string>() );
612 else if ( item.is_boolean() )
614 v = item.get<
bool>();
616 else if ( item.is_null() )
623 if ( type != QMetaType::Type::UnknownType )
625 if ( !v.convert(
static_cast<int>( type ) ) )
627 QgsLogger::warning( u
"Cannot convert json array element to specified type, ignoring: %1"_s.arg( v.toString() ) );
631 result.push_back( v );
636 result.push_back( v );
640 catch ( json::parse_error &ex )
642 errorMessage = ex.what();
656 if ( !coords.is_array() || coords.size() < 2 || coords.size() > 4 )
658 QgsDebugError( u
"JSON Point geometry coordinates must be an array of two, three or four numbers"_s );
662 const double x = coords[0].get<
double >();
663 const double y = coords[1].get<
double >();
664 if ( coords.size() == 2 )
666 return std::make_unique< QgsPoint >( x, y );
668 else if ( coords.size() == 3 )
670 const double zOrM = coords[2].get<
double >();
672 return std::make_unique< QgsPoint >( x, y, std::numeric_limits<double>::quiet_NaN(), zOrM );
674 return std::make_unique< QgsPoint >( x, y, zOrM );
678 const double z = coords[2].get<
double >();
679 const double m = coords[3].get<
double >();
680 return std::make_unique< QgsPoint >( x, y, z, m );
686 if ( !coords.is_array() )
688 QgsDebugError( u
"JSON LineString geometry coordinates must be an array"_s );
692 const std::size_t coordsSize = coords.size();
694 if ( coordsSize == 0 )
697 return std::make_unique< QgsLineString >();
700 if ( coordsSize < 2 )
702 QgsDebugError( u
"JSON LineString geometry coordinates must contain at least two positions"_s );
710 x.resize( coordsSize );
711 y.resize( coordsSize );
712 z.resize( coordsSize );
713 m.resize( coordsSize );
715 double *xOut = x.data();
716 double *yOut = y.data();
717 double *zOut = z.data();
718 double *mOut = m.data();
720 for (
const auto &coord : coords )
722 if ( !coord.is_array() || coord.size() < 2 || coord.size() > 4 )
724 QgsDebugError( u
"JSON LineString geometry coordinates must be an array of two, three or four numbers"_s );
728 *xOut++ = coord[0].get<
double >();
729 *yOut++ = coord[1].get<
double >();
730 if ( coord.size() == 4 )
732 *zOut++ = coord[2].get<
double >();
733 *mOut++ = coord[3].get<
double >();
735 else if ( coord.size() == 3 )
739 *mOut++ = coord[2].get<
double >();
740 *zOut++ = std::numeric_limits< double >::quiet_NaN();
744 *zOut++ = coord[2].get<
double >();
745 *mOut++ = std::numeric_limits< double >::quiet_NaN();
751 *zOut++ = std::numeric_limits< double >::quiet_NaN();
755 return std::make_unique< QgsLineString >( x, y, hasZ ? z : QVector<double>(), hasM ? m : QVector<double>() );
760 if ( !coords.is_array() )
762 QgsDebugError( u
"JSON Polygon geometry coordinates must be an array"_s );
766 if ( coords.empty() )
769 return std::make_unique< QgsPolygon >();
772 const std::size_t coordsSize = coords.size();
779 auto polygon = std::make_unique< QgsPolygon >( exterior.release() );
780 for ( std::size_t i = 1; i < coordsSize; ++i )
787 polygon->addInteriorRing( ring.release() );
794 const auto hasM = hasMIn || ( geometry.contains(
"measures" ) && geometry[
"measures"].contains(
"enabled" ) && geometry[
"measures"][
"enabled"].get<bool>() );
796 if ( !geometry.is_object() )
802 if ( !geometry.contains(
"type" ) )
808 const QString type = QString::fromStdString( geometry[
"type"].get< std::string >() );
809 if ( type.compare(
"Point"_L1, Qt::CaseInsensitive ) == 0 )
811 if ( !geometry.contains(
"coordinates" ) )
813 QgsDebugError( u
"JSON Point geometry must contain 'coordinates'"_s );
817 const json &coords = geometry[
"coordinates"];
820 else if ( type.compare(
"MultiPoint"_L1, Qt::CaseInsensitive ) == 0 )
822 if ( !geometry.contains(
"coordinates" ) )
824 QgsDebugError( u
"JSON MultiPoint geometry must contain 'coordinates'"_s );
828 const json &coords = geometry[
"coordinates"];
830 if ( !coords.is_array() )
832 QgsDebugError( u
"JSON MultiPoint geometry coordinates must be an array"_s );
836 auto multiPoint = std::make_unique< QgsMultiPoint >();
837 multiPoint->reserve(
static_cast< int >( coords.size() ) );
838 for (
const auto &pointCoords : coords )
845 multiPoint->addGeometry( point.release() );
850 else if ( type.compare(
"LineString"_L1, Qt::CaseInsensitive ) == 0 )
852 if ( !geometry.contains(
"coordinates" ) )
854 QgsDebugError( u
"JSON LineString geometry must contain 'coordinates'"_s );
858 const json &coords = geometry[
"coordinates"];
861 else if ( type.compare(
"MultiLineString"_L1, Qt::CaseInsensitive ) == 0 )
863 if ( !geometry.contains(
"coordinates" ) )
865 QgsDebugError( u
"JSON MultiLineString geometry must contain 'coordinates'"_s );
869 const json &coords = geometry[
"coordinates"];
871 if ( !coords.is_array() )
873 QgsDebugError( u
"JSON MultiLineString geometry coordinates must be an array"_s );
877 auto multiLineString = std::make_unique< QgsMultiLineString >();
878 multiLineString->reserve(
static_cast< int >( coords.size() ) );
879 for (
const auto &lineCoords : coords )
886 multiLineString->addGeometry( line.release() );
889 return multiLineString;
891 else if ( type.compare(
"Polygon"_L1, Qt::CaseInsensitive ) == 0 )
893 if ( !geometry.contains(
"coordinates" ) )
895 QgsDebugError( u
"JSON Polygon geometry must contain 'coordinates'"_s );
899 const json &coords = geometry[
"coordinates"];
900 if ( !coords.is_array() )
902 QgsDebugError( u
"JSON Polygon geometry coordinates must be an array"_s );
908 else if ( type.compare(
"MultiPolygon"_L1, Qt::CaseInsensitive ) == 0 )
910 if ( !geometry.contains(
"coordinates" ) )
912 QgsDebugError( u
"JSON MultiPolygon geometry must contain 'coordinates'"_s );
916 const json &coords = geometry[
"coordinates"];
918 if ( !coords.is_array() )
920 QgsDebugError( u
"JSON MultiPolygon geometry coordinates must be an array"_s );
924 auto multiPolygon = std::make_unique< QgsMultiPolygon >();
925 multiPolygon->reserve(
static_cast< int >( coords.size() ) );
926 for (
const auto &polygonCoords : coords )
933 multiPolygon->addGeometry( polygon.release() );
940 else if ( type.compare(
"CircularString"_L1, Qt::CaseInsensitive ) == 0 )
942 if ( !geometry.contains(
"coordinates" ) )
944 QgsDebugError( u
"JSON CircularString geometry must contain 'coordinates'"_s );
948 const json &coords = geometry[
"coordinates"];
950 if ( coords.empty() )
952 return std::make_unique< QgsCircularString >();
955 if ( !coords.is_array() || coords.size() % 2 == 0 || coords.size() < 3 )
957 QgsDebugError( u
"JSON CircularString geometry coordinates must be an array of at least 3 coordinates and the total number must be an odd number"_s );
961 const bool hasZ = coords[0].is_array() && ( coords[0].size() > 3 || ( coords[0].size() == 3 && !hasM ) );
964 x.reserve( coords.size() );
966 y.reserve( coords.size() );
969 z.reserve( coords.size() );
972 m.reserve( coords.size() );
974 for (
const auto &pointCoords : coords )
979 QgsDebugError( u
"Invalid point in CircularString geometry"_s );
982 x.append( point->x() );
983 y.append( point->y() );
985 z.append( point->z() );
987 m.append( point->m() );
989 return std::make_unique< QgsCircularString >( x, y, z, m );
991 else if ( type.compare(
"CompoundCurve"_L1, Qt::CaseInsensitive ) == 0 )
993 if ( !geometry.contains(
"geometries" ) )
995 QgsDebugError( u
"JSON CompoundCurve geometry must contain 'geometries'"_s );
998 const json &geometries = geometry[
"geometries"];
999 if ( !geometries.is_array() )
1001 QgsDebugError( u
"JSON CompoundCurve geometry geometries must be an array"_s );
1004 auto compoundCurve = std::make_unique< QgsCompoundCurve >();
1005 for (
const auto &geometry : geometries )
1015 QgsDebugError( u
"JSON CompoundCurve geometries must be of type LineString or CircularString"_s );
1018 compoundCurve->addCurve(
static_cast< QgsCurve *
>(
object.release() ) );
1020 return compoundCurve;
1022 else if ( type.compare(
"CurvePolygon"_L1, Qt::CaseInsensitive ) == 0 )
1024 if ( !geometry.contains(
"geometries" ) )
1026 QgsDebugError( u
"JSON CurvePolygon geometry must contain 'geometries'"_s );
1029 const json &geometries = geometry[
"geometries"];
1030 if ( !geometries.is_array() )
1032 QgsDebugError( u
"JSON CurvePolygon geometries must be an array"_s );
1035 auto curvePolygon = std::make_unique< QgsCurvePolygon>();
1036 bool isExterior =
true;
1037 for (
const auto &geometry : geometries )
1047 QgsDebugError( u
"JSON CurvePolygon geometries must be of type LineString, CircularString or CompoundCurve"_s );
1052 curvePolygon->setExteriorRing(
static_cast< QgsCurve *
>(
object.release() ) );
1057 curvePolygon->addInteriorRing(
static_cast< QgsCurve *
>(
object.release() ) );
1060 return curvePolygon;
1062 else if ( type.compare(
"MultiCurve"_L1, Qt::CaseInsensitive ) == 0 )
1064 if ( !geometry.contains(
"geometries" ) )
1066 QgsDebugError( u
"JSON MultiCurve geometry must contain 'geometries'"_s );
1069 const json &geometries = geometry[
"geometries"];
1070 if ( !geometries.is_array() )
1072 QgsDebugError( u
"JSON MultiCurve geometries must be an array"_s );
1075 auto multiCurve = std::make_unique< QgsMultiCurve>();
1076 for (
const auto &geometry : geometries )
1086 QgsDebugError( u
"JSON MultiCurve geometries must be of type LineString, CircularString or CompoundCurve"_s );
1089 multiCurve->addGeometry(
static_cast< QgsCurve *
>(
object.release() ) );
1093 else if ( type.compare(
"MultiSurface"_L1, Qt::CaseInsensitive ) == 0 )
1095 if ( !geometry.contains(
"geometries" ) )
1097 QgsDebugError( u
"JSON MultiSurface geometry must contain 'geometries'"_s );
1100 const json &geometries = geometry[
"geometries"];
1101 if ( !geometries.is_array() )
1103 QgsDebugError( u
"JSON MultiSurface geometries must be an array"_s );
1106 auto multiSurface = std::make_unique< QgsMultiSurface >();
1107 for (
const auto &geometry : geometries )
1117 QgsDebugError( u
"JSON MultiSurface geometries must be of type Polygon or CurvePolygon"_s );
1120 multiSurface->addGeometry(
static_cast< QgsSurface *
>(
object.release() ) );
1122 return multiSurface;
1124 else if ( type.compare(
"GeometryCollection"_L1, Qt::CaseInsensitive ) == 0 )
1126 if ( !geometry.contains(
"geometries" ) )
1128 QgsDebugError( u
"JSON GeometryCollection geometry must contain 'geometries'"_s );
1132 const json &geometries = geometry[
"geometries"];
1134 if ( !geometries.is_array() )
1136 QgsDebugError( u
"JSON GeometryCollection geometries must be an array"_s );
1140 auto collection = std::make_unique< QgsGeometryCollection >();
1141 collection->reserve(
static_cast< int >( geometries.size() ) );
1142 for (
const auto &geometry : geometries )
1149 collection->addGeometry(
object.release() );
1155 QgsDebugError( u
"Unhandled GeoJSON geometry type: %1"_s.arg( type ) );
1161 if ( !geometry.is_object() )
1163 QgsDebugError( u
"JSON geometry value must be an object"_s );
1174 const auto jObj( json::parse( geometry.toStdString() ) );
1177 catch ( json::parse_error &ex )
1179 QgsDebugError( u
"Cannot parse json (%1): %2"_s.arg( geometry, ex.what() ) );
1196 if ( val.userType() == QMetaType::Type::QVariantMap )
1198 const QVariantMap &vMap = val.toMap();
1199 json jMap = json::object();
1200 for (
auto it = vMap.constBegin(); it != vMap.constEnd(); it++ )
1206 else if ( val.userType() == QMetaType::Type::QVariantList || val.userType() == QMetaType::Type::QStringList )
1208 const QVariantList &vList = val.toList();
1209 json jList = json::array();
1210 for (
const auto &v : vList )
1218 switch ( val.userType() )
1220 case QMetaType::Int:
1221 case QMetaType::UInt:
1222 case QMetaType::LongLong:
1223 case QMetaType::ULongLong:
1224 j = val.toLongLong();
1226 case QMetaType::Double:
1227 case QMetaType::Float:
1230 case QMetaType::Bool:
1233 case QMetaType::QByteArray:
1234 j = val.toByteArray().toBase64().toStdString();
1237 j = val.toString().toStdString();
1247 const QVariant res =
parseJson( jsonString, error );
1249 if ( !error.isEmpty() )
1251 QgsLogger::warning( u
"Cannot parse json (%1): %2"_s.arg( error, QString::fromStdString( jsonString ) ) );
1261 const json j = json::parse( jsonString );
1264 catch ( json::parse_error &ex )
1266 error = QString::fromStdString( ex.what() );
1268 catch ( json::type_error &ex )
1270 error = QString::fromStdString( ex.what() );
1278 bool isPrimitive =
true;
1280 std::function<QVariant( json )> _parser { [&]( json jObj ) -> QVariant {
1282 if ( jObj.is_array() )
1284 isPrimitive =
false;
1285 QVariantList results;
1286 results.reserve( jObj.size() );
1287 for (
const auto &item : jObj )
1289 results.push_back( _parser( item ) );
1293 else if ( jObj.is_object() )
1295 isPrimitive =
false;
1296 QVariantMap results;
1297 for (
const auto &item : jObj.items() )
1299 const auto key { QString::fromStdString( item.key() ) };
1300 const auto value { _parser( item.value() ) };
1301 results[key] = value;
1307 if ( jObj.is_number_unsigned() )
1311 const qulonglong num { jObj.get<qulonglong>() };
1312 if ( num <= std::numeric_limits<int>::max() )
1314 result =
static_cast<int>( num );
1316 else if ( num <= std::numeric_limits<qlonglong>::max() )
1318 result =
static_cast<qlonglong
>( num );
1325 else if ( jObj.is_number_integer() )
1327 const qlonglong num { jObj.get<qlonglong>() };
1328 if ( num <= std::numeric_limits<int>::max() && num >= std::numeric_limits<int>::lowest() )
1330 result =
static_cast<int>( num );
1337 else if ( jObj.is_boolean() )
1339 result = jObj.get<
bool>();
1341 else if ( jObj.is_number_float() )
1344 result = jObj.get<
double>();
1346 else if ( jObj.is_string() )
1348 if ( isPrimitive && jObj.get<std::string>().length() == 0 )
1350 result = QString::fromStdString( jObj.get<std::string>() ).append(
"\"" ).insert( 0,
"\"" );
1354 result = QString::fromStdString( jObj.get<std::string>() );
1357 else if ( jObj.is_null() )
1365 return _parser( value );
1370 return jsonString.isEmpty() ? QVariant() :
parseJson( jsonString.toStdString() );
1377 for (
int i = 0; i < fields.
count(); ++i )
1381 if ( layer && useFieldFormatters )
1386 val = fieldFormatter->
representValue( layer, i, setup.
config(), attributeWidgetCaches.count() >= i ? attributeWidgetCaches.at( i ) : QVariant(), val );
1398 if ( crs.
authid() ==
"EPSG:4326" || crs.
authid() ==
"CRS:84" || crs.
authid() ==
"OGC:CRS84" )
1409 value[
"crs"][
"type"] =
"name";
1410 value[
"crs"][
"properties"][
"name"] = crs.
toOgcUrn().toStdString();
1416 value[
"coordRefSys"] = crs.
toOgcUri().toStdString();
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
GeoJsonProfile
GeoJson export Profile according to OGC Features and Geometries JSON - Part 1: Core https://docs....
@ Legacy
Legacy GeoJson profile used in QGIS prior to 4.2, which included some non-standard extensions and dev...
@ Rfc7946
GeoJson profile compliant with RFC7946 standard "http://www.opengis.net/def/profile/OGC/0/rfc7946".
@ JsonFg
GeoJson profile from OGC Features and Geometries JSON Part 1: core "http://www.opengis....
@ JsonFgPlus
GeoJson profile from OGC Features and Geometries JSON Part 1: core "http://www.opengis....
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CompoundCurve
CompoundCurve.
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
@ CircularString
CircularString.
@ GeometryCollection
GeometryCollection.
@ CurvePolygon
CurvePolygon.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString toOgcUri() const
Returns the crs as OGC URI (format: http://www.opengis.net/def/crs/OGC/1.3/CRS84) Returns an empty st...
QString toOgcUrn() const
Returns the crs as OGC URN (format: urn:ogc:def:crs:OGC:1.3:CRS84) Returns an empty string on failure...
Custom exception class for Coordinate Reference System related exceptions.
Abstract base class for curved geometry type.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
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.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
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)
Transforms this geometry as described by the coordinate transform ct.
virtual json asJsonObject(int precision=17, Qgis::GeoJsonProfile profile=Qgis::GeoJsonProfile::Legacy) const
Exports the geometry to a json object with the give precision and following the specified GeoJSON pro...
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.).
Qgis::GeoJsonProfile geoJsonProfile() const
Returns the GeoJSON profile to use for export.
json exportFeaturesToJsonObject(const QgsFeatureList &features) const
Returns a GeoJSON object representation of a list of features (feature collection).
void setSourceCrs(const QgsCoordinateReferenceSystem &crs)
Sets the source CRS for feature geometries.
QString exportFeature(const QgsFeature &feature, const QVariantMap &extraProperties=QVariantMap(), const QVariant &id=QVariant(), int indent=-1, const QVariantMap &extraMembers=QVariantMap()) const
Returns a GeoJSON string representation of a feature.
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.
int precision() const
Returns the maximum number of decimal places to use in geometry coordinates.
void setGeoJsonProfile(Qgis::GeoJsonProfile profile)
Sets the GeoJSON profile to use for export.
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.
json exportFeatureToJsonObject(const QgsFeature &feature, const QVariantMap &extraProperties=QVariantMap(), const QVariant &id=QVariant(), const QVariantMap &extraMembers=QVariantMap()) const
Returns a GeoJson representation of a feature.
static void addCrsInfo(json &value, const QgsCoordinateReferenceSystem &crs, Qgis::GeoJsonProfile profile=Qgis::GeoJsonProfile::Legacy)
Add crs information entry in json object regarding old GeoJSON specification format if it differs fro...
static QgsGeometry geometryFromGeoJson(const json &geometry)
Parses a GeoJSON "geometry" value to a QgsGeometry object.
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 QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields=QgsFields(), QTextCodec *encoding SIP_PYARGREMOVE6=nullptr)
Attempts to parse a GeoJSON string to a collection of features.
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 QVariant geometryToGeoJsonVariant(const QgsGeometry &geometry)
Converts a geometry to a GeoJSON compatible variant.
static Q_INVOKABLE QVariantList parseArray(const QString &json, QMetaType::Type type=QMetaType::Type::UnknownType)
Parse a simple array (depth=1).
static json exportAttributesToJsonObject(const QgsFeature &feature, QgsVectorLayer *layer=nullptr, const QVector< QVariant > &attributeWidgetCaches=QVector< QVariant >(), bool useFieldFormatters=true)
Exports all attributes from a QgsFeature as a json object.
static QVariant jsonToVariant(const json &value)
Converts a JSON value to a QVariant, in case of parsing error an invalid QVariant is returned.
static QgsFields stringToFields(const QString &string, QTextCodec *encoding SIP_PYARGREMOVE6=nullptr)
Attempts to retrieve the fields from a GeoJSON string representing a collection of features.
static json jsonFromVariant(const QVariant &v)
Converts a QVariant v to a json object.
static void warning(const QString &msg)
Goes to qWarning.
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.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
static QMetaType::Type variantTypeToMetaType(QVariant::Type variantType)
Converts a QVariant::Type to a QMetaType::Type.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
Represents a vector layer which manages a vector based dataset.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
static Qgis::WkbType flatType(Qgis::WkbType type)
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
std::unique_ptr< QgsAbstractGeometry > parseGeometryFromGeoJson(const json &geometry, bool hasMIn=false)
std::unique_ptr< QgsPolygon > parsePolygonFromGeoJson(const json &coords, bool hasM=false)
std::unique_ptr< QgsPoint > parsePointFromGeoJson(const json &coords, bool hasM=false)
std::unique_ptr< QgsLineString > parseLineStringFromGeoJson(const json &coords, bool hasM=false)
#define QgsDebugError(str)