Repository: geopandas/geopandas

Issue:
ENH: from_features - allow not passing in "properties"
https://github.com/geopandas/geopandas/blob/5c8ae832e030228b5deec02588c4e1b78dee0f18/geopandas/geodataframe.py#L651

It checks if `properties` is None. Any issues changing it to feature.get("properties") so this scenario could be supported:
```python
collection = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "id": "095af6d6-bfcd-4cca-a72c-bf2efd1cf917",
            "geometry": {
                "type": "Point",
                "coordinates": [-10.0, -10.0]
            }
        },
        {
            "type": "Feature",
            "id": "a7ad51b6-ad2d-4f75-806a-d68ab9e07e5b",
            "geometry": {
                "type": "Point",
                "coordinates": [-10.1, -10.1]
            }
        }
    ]
}
gdf = geopandas.GeoDataFrame.from_features(collection["features"])
```


Discussion:
Hey! Can I work on this?
@snowman2 sounds like a reasonable proposal.

@JorgChrist go for it! Let us know if you'll need any guidance.



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 059450d036..fd2f305ceb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog
 
+## Version 1.2.0
+
+Bug fixes:
+
+- Fix an issue that caused an error in `GeoDataFrame.from_features` when there is no `properties` field (#3599).
+
 ## Version 1.1.1 (June 27, 2025)
 
 Bug fixes:
diff --git a/geopandas/geodataframe.py b/geopandas/geodataframe.py
index 2cbee29d07..93b8f87010 100644
--- a/geopandas/geodataframe.py
+++ b/geopandas/geodataframe.py
@@ -815,9 +815,7 @@ def from_features(
                 "geometry": shape(feature["geometry"]) if feature["geometry"] else None
             }
             # load properties
-            properties = feature["properties"]
-            if properties is None:
-                properties = {}
+            properties = feature.get("properties") or {}
             row.update(properties)
             rows.append(row)
         return cls(rows, columns=columns, crs=crs)


Test patch:
diff --git a/geopandas/tests/test_geodataframe.py b/geopandas/tests/test_geodataframe.py
index 61eac57b37..698251c684 100644
--- a/geopandas/tests/test_geodataframe.py
+++ b/geopandas/tests/test_geodataframe.py
@@ -774,6 +774,26 @@ def test_from_features_empty_properties(self):
         gdf2 = GeoDataFrame.from_features(gjson_null)
 
         assert_frame_equal(gdf1, gdf2)
+        assert "properties" not in gdf1.columns
+
+    def test_from_features_no_properties(self):
+        data = {
+            "type": "FeatureCollection",
+            "features": [
+                {
+                    "type": "Feature",
+                    "geometry": {"type": "Point", "coordinates": [0.0, 90.0]},
+                },
+                {
+                    "type": "Feature",
+                    "geometry": {"type": "Point", "coordinates": [0.0, -90.0]},
+                },
+            ],
+        }
+
+        gdf = GeoDataFrame.from_features(data)
+        assert gdf.shape == (2, 1)
+        assert "properties" not in gdf.columns
 
     def test_from_features_geom_interface_feature(self):
         class Placemark: