Indent on JSON export

This commit is contained in:
Alessandro Pasotti 2019-05-03 19:02:58 +02:00
parent 290909f9bb
commit bd3d75fce8
8 changed files with 638 additions and 476 deletions

View File

@ -219,7 +219,8 @@ take precedence over attributes included via attributes().
QString exportFeature( const QgsFeature &feature,
const QVariantMap &extraProperties = QVariantMap(),
const QVariant &id = QVariant() ) const;
const QVariant &id = QVariant(),
int indent = -1 ) const;
%Docstring
Returns a GeoJSON string representation of a feature.
@ -227,6 +228,7 @@ Returns a GeoJSON string representation of a feature.
:param extraProperties: map of extra attributes to include in feature's properties
:param id: optional ID to use as GeoJSON feature's ID instead of input feature's ID. If omitted, feature's
ID is used.
:param indent: number of indentation spaces for generated JSON (defaults to none)
:return: GeoJSON string
@ -237,11 +239,12 @@ Returns a GeoJSON string representation of a feature.
QString exportFeatures( const QgsFeatureList &features ) const;
QString exportFeatures( const QgsFeatureList &features, int indent = -1 ) const;
%Docstring
Returns a GeoJSON string representation of a list of features (feature collection).
:param features: features to convert
:param indent: number of indentation spaces for generated JSON (defaults to none)
:return: GeoJSON string

View File

@ -69,9 +69,9 @@ QgsCoordinateReferenceSystem QgsJsonExporter::sourceCrs() const
}
QString QgsJsonExporter::exportFeature( const QgsFeature &feature, const QVariantMap &extraProperties,
const QVariant &id ) const
const QVariant &id, int indent ) const
{
return QString::fromStdString( exportFeatureToJsonObject( feature, extraProperties, id ).dump() );
return QString::fromStdString( exportFeatureToJsonObject( feature, extraProperties, id ).dump( indent ) );
}
json QgsJsonExporter::exportFeatureToJsonObject( const QgsFeature &feature, const QVariantMap &extraProperties, const QVariant &id ) const
@ -82,7 +82,16 @@ json QgsJsonExporter::exportFeatureToJsonObject( const QgsFeature &feature, cons
};
if ( id.isValid() )
{
featureJson["id"] = id.toString().toStdString();
bool ok = false;
auto intId = id.toLongLong( &ok );
if ( ok )
{
featureJson["id"] = intId;
}
else
{
featureJson["id"] = id.toString().toStdString();
}
}
else
{
@ -213,15 +222,19 @@ json QgsJsonExporter::exportFeatureToJsonObject( const QgsFeature &feature, cons
return featureJson;
}
QString QgsJsonExporter::exportFeatures( const QgsFeatureList &features ) const
QString QgsJsonExporter::exportFeatures( const QgsFeatureList &features, int indent ) const
{
QStringList featureJSON;
json data
{
{ "type", "FeatureCollection" },
{ "features", json::array() }
};
const auto constFeatures = features;
for ( const QgsFeature &feature : constFeatures )
{
featureJSON << exportFeature( feature );
data["features"].push_back( exportFeatureToJsonObject( feature ) );
}
return QStringLiteral( "{ \"type\": \"FeatureCollection\",\n \"features\":[\n%1\n]}" ).arg( featureJSON.join( QStringLiteral( ",\n" ) ) );
return QString::fromStdString( data.dump( indent ) );
}
//
@ -328,19 +341,41 @@ QVariantList QgsJsonUtils::parseArray( const QString &json, QVariant::Type type
json QgsJsonUtils::jsonFromVariant( const QVariant &val )
{
switch ( val.userType() )
if ( val.type() == QVariant::Type::Map )
{
case QMetaType::Int:
case QMetaType::UInt:
case QMetaType::LongLong:
case QMetaType::ULongLong:
return val.toLongLong();
case QMetaType::Double:
case QMetaType::Float:
return val.toDouble();
default:
return val.toString().toStdString();
const auto vMap { val.toMap() };
auto jMap { json::object() };
for ( auto it = vMap.constBegin(); it != vMap.constEnd(); it++ )
{
jMap[ it.key().toStdString() ] = jsonFromVariant( it.value() );
}
return jMap;
}
else if ( val.type() == QVariant::Type::List )
{
const auto vList{ val.toList() };
auto jList { json::array() };
for ( const auto &v : vList )
{
jList.push_back( jsonFromVariant( v ) );
}
return jList;
}
else
{
switch ( val.userType() )
{
case QMetaType::Int:
case QMetaType::UInt:
case QMetaType::LongLong:
case QMetaType::ULongLong:
return val.toLongLong();
case QMetaType::Double:
case QMetaType::Float:
return val.toDouble();
default:
return val.toString().toStdString();
}
}
}

View File

@ -198,13 +198,15 @@ class CORE_EXPORT QgsJsonExporter
* \param extraProperties map of extra attributes to include in feature's properties
* \param id optional ID to use as GeoJSON feature's ID instead of input feature's ID. If omitted, feature's
* ID is used.
* \param indent number of indentation spaces for generated JSON (defaults to none)
* \returns GeoJSON string
* \see exportFeatures()
* \see exportFeatureToJsonObject()
*/
QString exportFeature( const QgsFeature &feature,
const QVariantMap &extraProperties = QVariantMap(),
const QVariant &id = QVariant() ) const;
const QVariant &id = QVariant(),
int indent = -1 ) const;
/**
* Returns a QJsonObject representation of a feature.
@ -223,10 +225,11 @@ class CORE_EXPORT QgsJsonExporter
/**
* Returns a GeoJSON string representation of a list of features (feature collection).
* \param features features to convert
* \param indent number of indentation spaces for generated JSON (defaults to none)
* \returns GeoJSON string
* \see exportFeature()
*/
QString exportFeatures( const QgsFeatureList &features ) const;
QString exportFeatures( const QgsFeatureList &features, int indent = -1 ) const;
private:

View File

@ -157,24 +157,11 @@ void TestQgisAppClipboard::copyToText()
// GeoJSON
settings.setEnumValue( QStringLiteral( "/qgis/copyFeatureFormat" ), QgsClipboard::GeoJSON );
result = mQgisApp->clipboard()->generateClipboardText();
QString expected = "{ \"type\": \"FeatureCollection\",\n \"features\":[\n"
"{\n \"type\":\"Feature\",\n"
" \"id\":5,\n"
" \"geometry\":\n"
" {\"type\": \"Point\", \"coordinates\": [5, 6]},\n"
" \"properties\":{\n"
" \"int_field\":9,\n"
" \"string_field\":\"val\"\n"
" }\n"
"},\n"
"{\n \"type\":\"Feature\",\n"
" \"id\":6,\n"
" \"geometry\":\n"
" {\"type\": \"Point\", \"coordinates\": [7, 8]},\n"
" \"properties\":{\n"
" \"int_field\":19,\n"
" \"string_field\":\"val2\"\n"
" }\n}\n]}";
QString expected = "{\"features\":[{\"geometry\":{\"coordinates\":[5.0,6.0],\"type\":\"Point\"},\"id\":5,"
"\"properties\":{\"int_field\":9,\"string_field\":\"val\"},\"type\":\"Feature\"},"
"{\"geometry\":{\"coordinates\":[7.0,8.0],\"type\":\"Point\"},\"id\":6,"
"\"properties\":{\"int_field\":19,\"string_field\":\"val2\"},\"type\":\"Feature\"}],"
"\"type\":\"FeatureCollection\"}";
QCOMPARE( result, expected );
// test CRS is transformed correctly for GeoJSON
@ -191,7 +178,7 @@ void TestQgisAppClipboard::copyToText()
// just test coordinates as integers - that's enough to verify that reprojection has occurred
// and helps avoid rounding issues
QRegExp regex( "\\[([-\\d.]+), ([-\\d.]+)\\]" );
QRegExp regex( "\\[([-\\d.]+),([-\\d.]+)\\]" );
( void )regex.indexIn( result );
QStringList list = regex.capturedTexts();
QCOMPARE( list.count(), 3 );

View File

@ -174,17 +174,22 @@ class TestQgsJsonUtils(unittest.TestCase):
exporter = QgsJsonExporter()
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":{
"name":"Valsier Peninsula",
"cost":6.8,
"population":198
}
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": {
"cost": 6.8,
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
# test with linestring for bbox inclusion
l = QgsLineString()
@ -192,35 +197,58 @@ class TestQgsJsonUtils(unittest.TestCase):
feature.setGeometry(QgsGeometry(QgsLineString(l)))
expected = """{
"type":"Feature",
"id":5,
"bbox":[5, 6, 15, 16],
"geometry":
{"type": "LineString", "coordinates": [ [5, 6], [15, 16]]},
"properties":{
"name":"Valsier Peninsula",
"cost":6.8,
"population":198
}
"bbox": [
[
5.0,
6.0,
15.0,
16.0
]
],
"geometry": {
"coordinates": [
[
5.0,
6.0
],
[
15.0,
16.0
]
],
"type": "LineString"
},
"id": 5,
"properties": {
"cost": 6.8,
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
# test that precision is respected
feature.setGeometry(QgsGeometry(QgsPoint(5.444444444, 6.333333333)))
exporter.setPrecision(3)
self.assertEqual(exporter.precision(), 3)
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5.444, 6.333]},
"properties":{
"name":"Valsier Peninsula",
"cost":6.8,
"population":198
}
"geometry": {
"coordinates": [
5.444,
6.333
],
"type": "Point"
},
"id": 5,
"properties": {
"cost": 6.8,
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
feature.setGeometry(QgsGeometry(QgsPoint(5, 6)))
exporter.setPrecision(17)
@ -228,29 +256,39 @@ class TestQgsJsonUtils(unittest.TestCase):
exporter.setAttributes([0, 2])
self.assertEqual(exporter.attributes(), [0, 2])
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":{
"name":"Valsier Peninsula",
"population":198
}
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": {
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
exporter.setAttributes([1])
self.assertEqual(exporter.attributes(), [1])
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":{
"cost":6.8
}
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": {
"cost": 6.8
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
exporter.setAttributes([])
# text excluding attributes
@ -258,55 +296,75 @@ class TestQgsJsonUtils(unittest.TestCase):
exporter.setExcludedAttributes([1])
self.assertEqual(exporter.excludedAttributes(), [1])
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":{
"name":"Valsier Peninsula",
"population":198
}
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": {
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
exporter.setExcludedAttributes([1, 2])
self.assertEqual(exporter.excludedAttributes(), [1, 2])
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":{
"name":"Valsier Peninsula"
}
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": {
"name": "Valsier Peninsula"
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
exporter.setExcludedAttributes([0, 1, 2])
self.assertEqual(exporter.excludedAttributes(), [0, 1, 2])
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":null
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": null,
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
# test that excluded attributes take precedence over included
exporter.setAttributes([1, 2])
exporter.setExcludedAttributes([0, 1])
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":{
"population":198
}
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": {
"population": 198
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
exporter.setAttributes([])
exporter.setExcludedAttributes([])
@ -317,16 +375,16 @@ class TestQgsJsonUtils(unittest.TestCase):
feature.setGeometry(QgsGeometry(QgsLineString(l)))
expected = """{
"type":"Feature",
"id":5,
"geometry":null,
"properties":{
"name":"Valsier Peninsula",
"cost":6.8,
"population":198
}
"geometry": null,
"id": 5,
"properties": {
"cost": 6.8,
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
exporter.setIncludeGeometry(True)
feature.setGeometry(QgsGeometry(QgsPoint(5, 6)))
@ -335,76 +393,90 @@ class TestQgsJsonUtils(unittest.TestCase):
exporter.setIncludeAttributes(False)
self.assertEqual(exporter.includeAttributes(), False)
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":null
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": null,
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
exporter.setIncludeGeometry(False)
expected = """{
"type":"Feature",
"id":5,
"geometry":null,
"properties":null
"geometry": null,
"id": 5,
"properties": null,
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
exporter.setIncludeAttributes(True)
# test overriding ID
expected = """{
"type":"Feature",
"id":29,
"geometry":null,
"properties":{
"name":"Valsier Peninsula",
"cost":6.8,
"population":198
}
"geometry": null,
"id": 29,
"properties": {
"cost": 6.8,
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature, id=29), expected)
self.assertEqual(exporter.exportFeature(feature, id=29, indent=2), expected)
expected = """{
"geometry": null,
"id": "mylayer.29",
"properties": {
"cost": 6.8,
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature, id="mylayer.29", indent=2), expected)
# test injecting extra attributes
expected = """{
"type":"Feature",
"id":5,
"geometry":null,
"properties":{
"name":"Valsier Peninsula",
"cost":6.8,
"population":198,
"extra":"val1",
"extra2":2
}
"geometry": null,
"id": 5,
"properties": {
"cost": 6.8,
"extra": "val1",
"extra2": 2,
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature, extraProperties={"extra": "val1", "extra2": 2}), expected)
self.assertEqual(exporter.exportFeature(feature, extraProperties={"extra": "val1", "extra2": 2}, indent=2), expected)
exporter.setIncludeAttributes(False)
expected = """{
"type":"Feature",
"id":5,
"geometry":null,
"properties":{
"extra":"val1",
"extra2":{"nested_map":5,
"nested_map2":"val"},
"extra3":[1,2,3]
}
"geometry": null,
"id": 5,
"properties": {
"extra": "val1",
"extra2": {
"nested_map": 5,
"nested_map2": "val"
},
"extra3": [
1,
2,
3
]
},
"type": "Feature"
}"""
expected2 = """{
"type":"Feature",
"id":5,
"geometry":null,
"properties":{
"extra":"val1",
"extra2":{"nested_map":5,"nested_map2":"val"},
"extra3":[1,2,3]
}
}"""
exp_f = exporter.exportFeature(feature, extraProperties={"extra": "val1", "extra2": {"nested_map": 5, "nested_map2": "val"}, "extra3": [1, 2, 3]})
self.assertTrue(exp_f == expected or exp_f == expected2)
exp_f = exporter.exportFeature(feature, extraProperties={"extra": "val1", "extra2": {"nested_map": 5, "nested_map2": "val"}, "extra3": [1, 2, 3]}, indent=2)
self.assertEqual(exp_f, expected)
exporter.setIncludeGeometry(True)
def testExportFeatureFieldFormatter(self):
@ -429,15 +501,15 @@ class TestQgsJsonUtils(unittest.TestCase):
exporter.setVectorLayer(source)
expected = """{
"type":"Feature",
"id":0,
"geometry":null,
"properties":{
"fldtxt":"test1",
"fldint":"one"
}
"geometry": null,
"id": 0,
"properties": {
"fldint": "one",
"fldtxt": "test1"
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(pf1), expected)
self.assertEqual(exporter.exportFeature(pf1, indent=2), expected)
def testExportFeatureCrs(self):
""" Test CRS transform when exporting features """
@ -468,15 +540,20 @@ class TestQgsJsonUtils(unittest.TestCase):
# low precision, only need rough coordinate to check and don't want to deal with rounding errors
exporter.setPrecision(1)
expected = """{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [145, -37.9]},
"properties":{
"fldtxt":"test point"
}
"geometry": {
"coordinates": [
145.0,
-37.9
],
"type": "Point"
},
"id": 5,
"properties": {
"fldtxt": "test point"
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(feature), expected)
self.assertEqual(exporter.exportFeature(feature, indent=2), expected)
def testExportFeatureRelations(self):
""" Test exporting a feature with relations """
@ -528,90 +605,107 @@ class TestQgsJsonUtils(unittest.TestCase):
self.assertEqual(exporter.includeRelated(), True)
expected = """{
"type":"Feature",
"id":0,
"geometry":null,
"properties":{
"fldtxt":"test1",
"fldint":67,
"foreignkey":123,
"relation one":[{"x":"foo",
"y":123,
"z":321},
{"x":"bar",
"y":123,
"z":654}]
}
"geometry": null,
"id": 0,
"properties": {
"fldint": 67,
"fldtxt": "test1",
"foreignkey": 123,
"relation one": [
{
"x": "foo",
"y": 123,
"z": 321
},
{
"x": "bar",
"y": 123,
"z": 654
}
]
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(pf1), expected)
self.assertEqual(exporter.exportFeature(pf1, indent=2), expected)
expected = """{
"type":"Feature",
"id":0,
"geometry":null,
"properties":{
"fldtxt":"test2",
"fldint":68,
"foreignkey":124,
"relation one":[{"x":"foobar",
"y":124,
"z":554}]
}
"geometry": null,
"id": 0,
"properties": {
"fldint": 68,
"fldtxt": "test2",
"foreignkey": 124,
"relation one": [
{
"x": "foobar",
"y": 124,
"z": 554
}
]
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(pf2), expected)
self.assertEqual(exporter.exportFeature(pf2, indent=2), expected)
# with field formatter
setup = QgsEditorWidgetSetup('ValueMap', {"map": {"apples": 123, "bananas": 124}})
child.setEditorWidgetSetup(1, setup)
expected = """{
"type":"Feature",
"id":0,
"geometry":null,
"properties":{
"fldtxt":"test1",
"fldint":67,
"foreignkey":123,
"relation one":[{"x":"foo",
"y":"apples",
"z":321},
{"x":"bar",
"y":"apples",
"z":654}]
}
"geometry": null,
"id": 0,
"properties": {
"fldint": 67,
"fldtxt": "test1",
"foreignkey": 123,
"relation one": [
{
"x": "foo",
"y": "apples",
"z": 321
},
{
"x": "bar",
"y": "apples",
"z": 654
}
]
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(pf1), expected)
self.assertEqual(exporter.exportFeature(pf1, indent=2), expected)
# test excluding related attributes
exporter.setIncludeRelated(False)
self.assertEqual(exporter.includeRelated(), False)
expected = """{
"type":"Feature",
"id":0,
"geometry":null,
"properties":{
"fldtxt":"test2",
"fldint":68,
"foreignkey":124
}
"geometry": null,
"id": 0,
"properties": {
"fldint": 68,
"fldtxt": "test2",
"foreignkey": 124
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(pf2), expected)
self.assertEqual(exporter.exportFeature(pf2, indent=2), expected)
# test without vector layer set
exporter.setIncludeRelated(True)
exporter.setVectorLayer(None)
expected = """{
"type":"Feature",
"id":0,
"geometry":null,
"properties":{
"fldtxt":"test2",
"fldint":68,
"foreignkey":124
}
"geometry": null,
"id": 0,
"properties": {
"fldint": 68,
"fldtxt": "test2",
"foreignkey": 124
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(pf2), expected)
self.assertEqual(exporter.exportFeature(pf2, indent=2), expected)
def testExportFeatures(self):
""" Test exporting feature collections """
@ -628,53 +722,72 @@ class TestQgsJsonUtils(unittest.TestCase):
exporter = QgsJsonExporter()
# single feature
expected = """{ "type": "FeatureCollection",
"features":[
{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":{
"name":"Valsier Peninsula",
"cost":6.8,
"population":198
}
}
]}"""
self.assertEqual(exporter.exportFeatures([feature]), expected)
expected = """{
"features": [
{
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": {
"cost": 6.8,
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
}
],
"type": "FeatureCollection"
}"""
self.assertEqual(exporter.exportFeatures([feature], 2), expected)
# multiple features
feature2 = QgsFeature(fields, 6)
feature2.setGeometry(QgsGeometry(QgsPoint(7, 8)))
feature2.setAttributes(['Henry Gale Island', 9.7, 38])
expected = """{ "type": "FeatureCollection",
"features":[
{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":{
"name":"Valsier Peninsula",
"cost":6.8,
"population":198
}
},
{
"type":"Feature",
"id":6,
"geometry":
{"type": "Point", "coordinates": [7, 8]},
"properties":{
"name":"Henry Gale Island",
"cost":9.7,
"population":38
}
}
]}"""
self.assertEqual(exporter.exportFeatures([feature, feature2]), expected)
expected = """{
"features": [
{
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": {
"cost": 6.8,
"name": "Valsier Peninsula",
"population": 198
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
7.0,
8.0
],
"type": "Point"
},
"id": 6,
"properties": {
"cost": 9.7,
"name": "Henry Gale Island",
"population": 38
},
"type": "Feature"
}
],
"type": "FeatureCollection"
}"""
self.assertEqual(exporter.exportFeatures([feature, feature2], 2), expected)
def testExportFeaturesWithLocale_regression20053(self):
""" Test exporting feature export with range widgets and locale different than C
@ -693,22 +806,29 @@ class TestQgsJsonUtils(unittest.TestCase):
exporter = QgsJsonExporter()
# single feature
expected = """{ "type": "FeatureCollection",
"features":[
{
"type":"Feature",
"id":5,
"geometry":
{"type": "Point", "coordinates": [5, 6]},
"properties":{
"name":"Valsier Peninsula",
"cost":6.8,
"population":198000,
"date":"2018-09-10"
}
}
]}"""
self.assertEqual(exporter.exportFeatures([feature]), expected)
expected = """{
"features": [
{
"geometry": {
"coordinates": [
5.0,
6.0
],
"type": "Point"
},
"id": 5,
"properties": {
"cost": 6.8,
"date": "2018-09-10",
"name": "Valsier Peninsula",
"population": 198000
},
"type": "Feature"
}
],
"type": "FeatureCollection"
}"""
self.assertEqual(exporter.exportFeatures([feature], 2), expected)
setup = QgsEditorWidgetSetup('Range', {
'AllowNull': True,
@ -724,7 +844,7 @@ class TestQgsJsonUtils(unittest.TestCase):
QLocale.setDefault(QLocale('it'))
exporter.setVectorLayer(source)
self.assertEqual(exporter.exportFeatures([feature]), expected)
self.assertEqual(exporter.exportFeatures([feature], 2), expected)
def testExportFieldAlias(self):
""" Test exporting a feature with fields' alias """
@ -749,15 +869,15 @@ class TestQgsJsonUtils(unittest.TestCase):
exporter.setVectorLayer(source)
expected = """{
"type":"Feature",
"id":0,
"geometry":null,
"properties":{
"alias_fldtxt":"test1",
"alias_fldint":1
}
"geometry": null,
"id": 0,
"properties": {
"alias_fldint": 1,
"alias_fldtxt": "test1"
},
"type": "Feature"
}"""
self.assertEqual(exporter.exportFeature(pf1), expected)
self.assertEqual(exporter.exportFeature(pf1, indent=2), expected)
if __name__ == "__main__":

View File

@ -1,46 +1,50 @@
Content-Length: 992
*****
Content-Type: application/json; charset=utf-8
{"type": "FeatureCollection",
"features":[
{
"type":"Feature",
"id":"as_areas.18",
"geometry":null,
"properties":{
"fid":18,
"gid":34,
"datum":"2013-06-11",
"bearbeiter":"scholle-b",
"veranstaltung":"",
"beschriftung":"",
"name":"",
"flaechentyp":"Schraffur",
"farbe":"255 0 0",
"schraff_width":"2",
"schraff_width_prt":"6.00",
"schraff_size":"10",
"schraff_size_prt":"30.00",
"schraff_winkel":"45",
"umrissfarbe":"0 0 0",
"umrisstyp":"durchgezogen",
"umrissstaerke":"1",
"umrissstaerke_prt":"3.00",
"umfang":758.4703,
"flaeche":12879,
"bemerkung":"",
"last_change":"2013-06-11 10:03:45.52301+02"
}
},{
"type":"Feature",
"id":"cdb_lines.13",
"geometry":null,
"properties":{
"fid":13,
"id":12,
"typ":"Ortsteil",
"name":"Fallersleben",
"ortsrat":"Fallersleben\/Sülfeld",
"id_long":null
}
}]}
"features": [
{
"geometry": null,
"id": "as_areas.18",
"properties": {
"bearbeiter": "scholle-b",
"bemerkung": "",
"beschriftung": "",
"datum": "2013-06-11",
"farbe": "255 0 0",
"fid": 18,
"flaeche": 12879.0,
"flaechentyp": "Schraffur",
"gid": 34,
"last_change": "2013-06-11 10:03:45.52301+02",
"name": "",
"schraff_size": "10",
"schraff_size_prt": "30.00",
"schraff_width": "2",
"schraff_width_prt": "6.00",
"schraff_winkel": "45",
"umfang": 758.4703,
"umrissfarbe": "0 0 0",
"umrissstaerke": "1",
"umrissstaerke_prt": "3.00",
"umrisstyp": "durchgezogen",
"veranstaltung": ""
},
"type": "Feature"
},
{
"geometry": null,
"id": "cdb_lines.13",
"properties": {
"fid": 13,
"id": 12,
"id_long": "",
"name": "Fallersleben",
"ortsrat": "Fallersleben/Sülfeld",
"typ": "Ortsteil"
},
"type": "Feature"
}
],
"type": "FeatureCollection"
}

View File

@ -1,82 +1,89 @@
Content-Length: 1124
*****
Content-Type: application/json; charset=utf-8
{"type": "FeatureCollection",
"features":[
{
"type":"Feature",
"id":"cdb_lines.13",
"geometry":null,
"properties":{
"fid":13,
"id":12,
"typ":"Ortsteil",
"name":"Fallersleben",
"ortsrat":"Fallersleben\/Sülfeld",
"id_long":null
}
},{
"type":"Feature",
"id":"as_areas.18",
"geometry":null,
"properties":{
"fid":18,
"gid":34,
"datum":"2013-06-11",
"bearbeiter":"scholle-b",
"veranstaltung":"",
"beschriftung":"",
"name":"",
"flaechentyp":"Schraffur",
"farbe":"255 0 0",
"schraff_width":"2",
"schraff_width_prt":"6.00",
"schraff_size":"10",
"schraff_size_prt":"30.00",
"schraff_winkel":"45",
"umrissfarbe":"0 0 0",
"umrisstyp":"durchgezogen",
"umrissstaerke":"1",
"umrissstaerke_prt":"3.00",
"umfang":758.4703,
"flaeche":12879,
"bemerkung":"",
"last_change":"2013-06-11 10:03:45.52301+02"
}
},{
"type":"Feature",
"id":"as_areas_query_copy.18",
"geometry":null,
"properties":{
"fid":18,
"gid":34,
"datum":"2013-06-11",
"bearbeiter":"scholle-b",
"veranstaltung":"",
"beschriftung":"",
"name":"",
"flaechentyp":"Schraffur",
"farbe":"255 0 0",
"schraff_width":"2",
"schraff_width_prt":"6.00",
"schraff_size":"10",
"schraff_size_prt":"30.00",
"schraff_winkel":"45",
"umrissfarbe":"0 0 0",
"umrisstyp":"durchgezogen",
"umrissstaerke":"1",
"umrissstaerke_prt":"3.00",
"umfang":758.4703,
"flaeche":12879,
"bemerkung":"",
"last_change":"2013-06-11 10:03:45.52301+02"
}
},{"type":"Feature",
"id":"osm",
"properties":{
"Band 1": "255",
"Band 2": "255",
"Band 3": "255",
"Band 4": "255"
}
}]}
"features": [
{
"geometry": null,
"id": "cdb_lines.13",
"properties": {
"fid": 13,
"id": 12,
"id_long": "",
"name": "Fallersleben",
"ortsrat": "Fallersleben/Sülfeld",
"typ": "Ortsteil"
},
"type": "Feature"
},
{
"geometry": null,
"id": "as_areas.18",
"properties": {
"bearbeiter": "scholle-b",
"bemerkung": "",
"beschriftung": "",
"datum": "2013-06-11",
"farbe": "255 0 0",
"fid": 18,
"flaeche": 12879.0,
"flaechentyp": "Schraffur",
"gid": 34,
"last_change": "2013-06-11 10:03:45.52301+02",
"name": "",
"schraff_size": "10",
"schraff_size_prt": "30.00",
"schraff_width": "2",
"schraff_width_prt": "6.00",
"schraff_winkel": "45",
"umfang": 758.4703,
"umrissfarbe": "0 0 0",
"umrissstaerke": "1",
"umrissstaerke_prt": "3.00",
"umrisstyp": "durchgezogen",
"veranstaltung": ""
},
"type": "Feature"
},
{
"geometry": null,
"id": "as_areas_query_copy.18",
"properties": {
"bearbeiter": "scholle-b",
"bemerkung": "",
"beschriftung": "",
"datum": "2013-06-11",
"farbe": "255 0 0",
"fid": 18,
"flaeche": 12879.0,
"flaechentyp": "Schraffur",
"gid": 34,
"last_change": "2013-06-11 10:03:45.52301+02",
"name": "",
"schraff_size": "10",
"schraff_size_prt": "30.00",
"schraff_width": "2",
"schraff_width_prt": "6.00",
"schraff_winkel": "45",
"umfang": 758.4703,
"umrissfarbe": "0 0 0",
"umrissstaerke": "1",
"umrissstaerke_prt": "3.00",
"umrisstyp": "durchgezogen",
"veranstaltung": ""
},
"type": "Feature"
},
{
"id": "osm",
"properties": {
"Band 1": "255",
"Band 2": "255",
"Band 3": "255",
"Band 4": "255"
},
"type": "Feature"
}
],
"type": "FeatureCollection"
}

View File

@ -1,34 +1,37 @@
*****
Content-Type: application/json; charset=utf-8
{"type": "FeatureCollection",
"features":[
{
"type":"Feature",
"id":"as_areas_query_copy.18",
"geometry":null,
"properties":{
"fid":18,
"gid":34,
"datum":"2013-06-11",
"bearbeiter":"scholle-b",
"veranstaltung":"",
"beschriftung":"",
"name":"",
"flaechentyp":"Schraffur",
"farbe":"255 0 0",
"schraff_width":"2",
"schraff_width_prt":"6.00",
"schraff_size":"10",
"schraff_size_prt":"30.00",
"schraff_winkel":"45",
"umrissfarbe":"0 0 0",
"umrisstyp":"durchgezogen",
"umrissstaerke":"1",
"umrissstaerke_prt":"3.00",
"umfang":758.4703,
"flaeche":12879,
"bemerkung":"",
"last_change":"2013-06-11 10:03:45.52301+02"
}
}]}
"features": [
{
"geometry": null,
"id": "as_areas_query_copy.18",
"properties": {
"bearbeiter": "scholle-b",
"bemerkung": "",
"beschriftung": "",
"datum": "2013-06-11",
"farbe": "255 0 0",
"fid": 18,
"flaeche": 12879.0,
"flaechentyp": "Schraffur",
"gid": 34,
"last_change": "2013-06-11 10:03:45.52301+02",
"name": "",
"schraff_size": "10",
"schraff_size_prt": "30.00",
"schraff_width": "2",
"schraff_width_prt": "6.00",
"schraff_winkel": "45",
"umfang": 758.4703,
"umrissfarbe": "0 0 0",
"umrissstaerke": "1",
"umrissstaerke_prt": "3.00",
"umrisstyp": "durchgezogen",
"veranstaltung": ""
},
"type": "Feature"
}
],
"type": "FeatureCollection"
}