# `AshNeo4j.GeoJson`
[🔗](https://github.com/diffo-dev/ash_neo4j/blob/v0.10.1/lib/geo_json.ex#L5)

RFC 7946 GeoJSON encoder/decoder over the `:geo` library.

`Geo.JSON.encode!/1` produces the obsolete 2008-spec GeoJSON shape when
`srid` is set on a geometry struct — it adds a `"crs"` member that
[RFC 7946](https://datatracker.ietf.org/doc/html/rfc7946) explicitly
removed. AshNeo4j wants RFC 7946 strictly on disk (GIS-tool interop is
half the motivation), so this module wraps `Geo.JSON` to:

  - **Strip the `crs` member on encode** by nilling `srid` before
    handing the struct to `Geo.JSON.encode!/1`.
  - **Add the optional RFC `bbox` member** to every encoded geometry,
    derived from the coordinates. Makes the JSON self-describing for
    any consumer that doesn't want to recompute the bounding box.
  - **Set `srid: 4326` on decoded structs.** AshNeo4j is WGS-84 2D
    throughout; the struct should carry that explicitly even though
    the on-disk JSON omits the CRS.

Round-trip: `encode!(geom) |> decode!() == geom` (with `srid: 4326`
set on the decoded side).

The encode workaround is a candidate for an upstream fix in `:geo`
itself (an option like `Geo.JSON.encode!(geom, rfc7946: true)`); to
be filed once this local workaround is exercised in production.

# `bbox`

```elixir
@spec bbox(Geo.geometry()) :: [float()]
```

Derives the RFC 7946 §5 bbox for a geometry as `[west, south, east, north]`
(2D, WGS-84). Walks the coordinate structure recursively, so works for
any geometry shape — Point, LineString, Polygon (incl. holes),
MultiPoint, MultiLineString, MultiPolygon.

# `decode!`

```elixir
@spec decode!(String.t()) :: Geo.geometry()
```

Decodes an RFC 7946 GeoJSON string to a `%Geo.*{}` struct with the WGS-84
srid set by dimensionality — `4326` for 2D geometries, `4979` for 3D (a
third coordinate present, e.g. `%Geo.PointZ{}`). The on-disk JSON omits the
CRS member (RFC 7946), so the srid is inferred from the coordinate arity and
restored here. The `bbox` member, if present, is ignored — it's metadata
derivable from coordinates and the struct doesn't carry it.

# `encode!`

```elixir
@spec encode!(Geo.geometry()) :: String.t()
```

Encodes a `%Geo.*{}` struct to an RFC 7946-compliant GeoJSON string
with the `bbox` member included. Keys are sorted alphabetically via
`AshNeo4j.Util.json_encode/1` for stable on-disk ordering.

# `encode_map`

```elixir
@spec encode_map(Geo.geometry()) :: map()
```

Encodes a `%Geo.*{}` struct to an RFC 7946 GeoJSON **map** (without
JSON-stringifying). Used when the GeoJSON needs to be nested inside
another structure that will itself be JSON-encoded — e.g. a Geo struct
living inside a TypedStruct attribute, where the parent's JSON blob
contains the nested GeoJSON inline.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
