Skip to content

Commit

Permalink
newline-delimited GeoJSON writer (#535)
Browse files Browse the repository at this point in the history
  • Loading branch information
kylebarron authored Feb 26, 2024
1 parent 0ec47c3 commit 99b7cfe
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 7 deletions.
11 changes: 7 additions & 4 deletions python/core/python/geoarrow/rust/core/_rust.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -1239,20 +1239,20 @@ def read_csv(
batch_size: int = 65536,
) -> GeoTable: ...
def read_flatgeobuf(
file: Union[str, Path, BinaryIO], batch_size: int = 65536
file: Union[str, Path, BinaryIO], *, batch_size: int = 65536
) -> GeoTable: ...
async def read_flatgeobuf_async(
url: str, *, batch_size: int = 65536, options: Dict[str, str] | None = None
) -> GeoTable: ...
def read_geojson(
file: Union[str, Path, BinaryIO], batch_size: int = 65536
file: Union[str, Path, BinaryIO], *, batch_size: int = 65536
) -> GeoTable: ...
def read_geojson_lines(
file: Union[str, Path, BinaryIO], batch_size: int = 65536
file: Union[str, Path, BinaryIO], *, batch_size: int = 65536
) -> GeoTable: ...
def read_ipc(file: Union[str, Path, BinaryIO]) -> GeoTable: ...
def read_ipc_stream(file: Union[str, Path, BinaryIO]) -> GeoTable: ...
def read_parquet(path: str, batch_size: int = 65536) -> GeoTable: ...
def read_parquet(path: str, *, batch_size: int = 65536) -> GeoTable: ...
def read_postgis(connection_url: str, sql: str) -> Optional[GeoTable]: ...
async def read_postgis_async(connection_url: str, sql: str) -> Optional[GeoTable]: ...
def read_pyogrio(
Expand Down Expand Up @@ -1284,6 +1284,9 @@ def write_flatgeobuf(
def write_geojson(
table: ArrowStreamExportable, file: Union[str, Path, BinaryIO]
) -> None: ...
def write_geojson_lines(
table: ArrowStreamExportable, file: Union[str, Path, BinaryIO]
) -> None: ...
def write_ipc(
table: ArrowStreamExportable, file: Union[str, Path, BinaryIO]
) -> None: ...
Expand Down
27 changes: 25 additions & 2 deletions python/core/src/io/geojson_lines.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::error::PyGeoArrowResult;
use crate::io::file::BinaryFileReader;
use crate::io::file::{BinaryFileReader, BinaryFileWriter};
use crate::table::GeoTable;
use geoarrow::io::geojson_lines::read_geojson_lines as _read_geojson_lines;
use geoarrow::io::geojson_lines::write_geojson_lines as _write_geojson_lines;
use pyo3::prelude::*;

/// Read a GeoJSON Lines file from a path on disk into a GeoTable.
/// Read a newline-delimited GeoJSON file from a path on disk into a GeoTable.
///
/// This expects a GeoJSON Feature on each line of a text file, with a newline character separating
/// each Feature.
Expand All @@ -25,3 +26,25 @@ pub fn read_geojson_lines(
let table = _read_geojson_lines(&mut reader, Some(batch_size))?;
Ok(GeoTable(table))
}

/// Write a GeoTable to a newline-delimited GeoJSON file on disk.
///
/// Note that the GeoJSON specification mandates coordinates to be in the WGS84 (EPSG:4326)
/// coordinate system, but this function will not automatically reproject into WGS84 for you.
///
/// Args:
/// table: the table to write.
/// file: the path to the file or a Python file object in binary write mode.
///
/// Returns:
/// None
#[pyfunction]
pub fn write_geojson_lines(
py: Python,
mut table: GeoTable,
file: PyObject,
) -> PyGeoArrowResult<()> {
let writer = file.extract::<BinaryFileWriter>(py)?;
_write_geojson_lines(&mut table.0, writer)?;
Ok(())
}
4 changes: 4 additions & 0 deletions python/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ fn _rust(_py: Python, m: &PyModule) -> PyResult<()> {
m
)?)?;
m.add_function(wrap_pyfunction!(crate::io::geojson::write_geojson, m)?)?;
m.add_function(wrap_pyfunction!(
crate::io::geojson_lines::write_geojson_lines,
m
)?)?;

// Interop
m.add_function(wrap_pyfunction!(
Expand Down
1 change: 1 addition & 0 deletions python/docs/source/api/core/io.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Read and write to files on disk and databases like PostGIS.
- write_csv
- write_flatgeobuf
- write_geojson
- write_geojson_lines
- write_ipc
- write_ipc_stream
- write_parquet
4 changes: 3 additions & 1 deletion src/io/geojson_lines/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Read from [newline-delimited GeoJSON](https://stevage.github.io/ndgeojson/) files.
//! Read from and write to [newline-delimited GeoJSON](https://stevage.github.io/ndgeojson/) files.

mod reader;
mod writer;

pub use reader::read_geojson_lines;
pub use writer::write_geojson_lines;
13 changes: 13 additions & 0 deletions src/io/geojson_lines/writer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use geozero::geojson::GeoJsonLineWriter;
use geozero::GeozeroDatasource;
use std::io::Write;

use crate::error::Result;
use crate::table::GeoTable;

/// Write a table to newline-delimited GeoJSON
pub fn write_geojson_lines<W: Write>(table: &mut GeoTable, writer: W) -> Result<()> {
let mut geojson_writer = GeoJsonLineWriter::new(writer);
table.process(&mut geojson_writer)?;
Ok(())
}

0 comments on commit 99b7cfe

Please sign in to comment.