{"id":26380689,"url":"https://github.com/nramc/geojson4j","last_synced_at":"2026-05-10T10:27:43.578Z","repository":{"id":261248476,"uuid":"883735158","full_name":"nramc/geojson4j","owner":"nramc","description":"A Java library for working with GeoJSON data, compliant with RFC 7946.  GeoJSON4j provides easy-to-use utilities for creating, parsing, and serializing GeoJSON objects, such as Points, LineStrings, Polygons, and FeatureCollections, while fully adhering to the official GeoJSON specification (RFC 7946).","archived":false,"fork":false,"pushed_at":"2026-02-23T10:05:34.000Z","size":542,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-23T18:55:18.247Z","etag":null,"topics":["geojson","geojson-library","geojson-parser","geojson4j","java","json-parser","open-source","rfc-7946"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nramc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-05T13:37:32.000Z","updated_at":"2026-02-23T10:05:20.000Z","dependencies_parsed_at":"2024-11-21T18:31:38.810Z","dependency_job_id":"0b2b091a-5d4c-462a-b07c-3d0ed656101e","html_url":"https://github.com/nramc/geojson4j","commit_stats":null,"previous_names":["nramc/geojson4j"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/nramc/geojson4j","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nramc%2Fgeojson4j","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nramc%2Fgeojson4j/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nramc%2Fgeojson4j/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nramc%2Fgeojson4j/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nramc","download_url":"https://codeload.github.com/nramc/geojson4j/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nramc%2Fgeojson4j/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29986256,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T21:06:37.093Z","status":"ssl_error","status_checked_at":"2026-03-01T21:05:45.052Z","response_time":124,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["geojson","geojson-library","geojson-parser","geojson4j","java","json-parser","open-source","rfc-7946"],"created_at":"2025-03-17T05:32:56.264Z","updated_at":"2026-05-10T10:27:43.560Z","avatar_url":"https://github.com/nramc.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# geojson4j\n\n**A lightweight, RFC 7946-compliant GeoJSON library for Java**\n\n[![CI](https://img.shields.io/github/actions/workflow/status/nramc/geojson4j/ci-workflow.yml?branch=main\u0026style=flat\u0026label=CI\u0026logo=github)](https://github.com/nramc/geojson4j/actions/workflows/ci-workflow.yml)\n[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=nramc_geojson4j\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=nramc_geojson4j)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=nramc_geojson4j\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=nramc_geojson4j)\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.nramc/geojson4j?style=flat\u0026logo=apachemaven\u0026logoColor=%23C71A36\u0026color=%2303C75A)](https://mvnrepository.com/artifact/io.github.nramc/geojson4j)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Java](https://img.shields.io/badge/Java-21-orange?logo=openjdk)](https://openjdk.org/projects/jdk/21/)\n\n[Getting Started](#installation) · [Usage](#usage) · [API Reference](#api-reference) · [Contributing](#contributing)\n\n\u003c/div\u003e\n\n---\n\n## What is geojson4j?\n\n**geojson4j** is a Java domain library for working\nwith [GeoJSON (RFC 7946)](https://datatracker.ietf.org/doc/html/rfc7946) data. It lets you create, parse, validate, and\nserialize all standard GeoJSON types using a fluent, type-safe API built on top of Jackson.\n\n### Why geojson4j?\n\n- ✅ **RFC 7946 compliant** — full specification coverage\n- 🔒 **Immutable domain objects** — thread-safe by design\n- ⚡ **Eager validation** — factory methods throw on invalid data; constructors stay deserialization-friendly\n- 🔌 **Jackson-native** — drop-in serialization/deserialization with `@JsonCreator` / `@JsonSubTypes` polymorphism\n- 🧪 **Well-tested** — serialization, deserialization, invalid states, and validation error keys all covered\n\n---\n\n## Supported GeoJSON Types\n\n| GeoJSON Type         | Java Class           | RFC 7946 Section |\n|----------------------|----------------------|------------------|\n| `Point`              | `Point`              | §3.1.2           |\n| `LineString`         | `LineString`         | §3.1.4           |\n| `Polygon`            | `Polygon`            | §3.1.6           |\n| `MultiPoint`         | `MultiPoint`         | §3.1.3           |\n| `MultiLineString`    | `MultiLineString`    | §3.1.5           |\n| `MultiPolygon`       | `MultiPolygon`       | §3.1.7           |\n| `GeometryCollection` | `GeometryCollection` | §3.1.8           |\n| `Feature`            | `Feature`            | §3.2             |\n| `FeatureCollection`  | `FeatureCollection`  | §3.3             |\n\n---\n\n## Installation\n\n**Requirements:** Java 21+, Maven or Gradle\n\n### Maven\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.nramc\u003c/groupId\u003e\n    \u003cartifactId\u003egeojson4j\u003c/artifactId\u003e\n    \u003cversion\u003e${geojson4j.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Gradle\n\n```groovy\nimplementation 'io.github.nramc:geojson4j:1.0.17'\n```\n\n\u003e Check [Maven Central](https://mvnrepository.com/artifact/io.github.nramc/geojson4j) for the latest version.\n\n---\n\n## Usage\n\n### Creating GeoJSON Objects\n\nUse the static `of(...)` factory methods. They validate eagerly and throw `GeoJsonValidationException` if the data is\ninvalid.\n\n```java\n// Point — longitude, latitude\nPoint point = Point.of(102.0, 0.5);\n\n// Point with altitude\nPoint point3d = Point.of(102.0, 0.5, 256.0);\n\n// LineString — varargs of Position\nLineString line = LineString.of(\n        Position.of(102.0, 0.0),\n        Position.of(103.0, 1.0),\n        Position.of(104.0, 0.0)\n);\n\n// Polygon — exterior ring must have ≥ 4 positions; first == last (closed)\n// PolygonCoordinates.of() accepts one or more List\u003cPosition\u003e rings (first = exterior)\nList\u003cPosition\u003e exterior = List.of(\n        Position.of(100.0, 0.0),\n        Position.of(101.0, 0.0),\n        Position.of(101.0, 1.0),\n        Position.of(100.0, 1.0),\n        Position.of(100.0, 0.0)   // close the ring\n);\nPolygon polygon = Polygon.of(exterior);\n\n// Feature — id (nullable), geometry, properties\nMap\u003cString, Serializable\u003e props = new HashMap\u003c\u003e();\nprops.put(\"name\", \"My Location\");\nprops.put(\"category\", \"landmark\");\nFeature feature = Feature.of(\"location-1\", point, props);\n\n// FeatureCollection\nFeatureCollection collection = FeatureCollection.of(List.of(feature));\n```\n\n### Serialization (Object → JSON)\n\n```java\nObjectMapper mapper = new ObjectMapper();\n\nPoint point = Point.of(102.0, 0.5);\nString json = mapper.writeValueAsString(point);\n// {\"type\":\"Point\",\"coordinates\":[102.0,0.5]}\n```\n\n### Deserialization (JSON → Object)\n\nDeserialize to a concrete type:\n\n```java\nString json = \"\"\"\n        { \"type\": \"Point\", \"coordinates\": [102.0, 0.5] }\n        \"\"\";\n\nObjectMapper mapper = new ObjectMapper();\nPoint point = mapper.readValue(json, Point.class);\n\ndouble lon = point.getCoordinates().getLongitude(); // 102.0\ndouble lat = point.getCoordinates().getLatitude();  // 0.5\n```\n\nDeserialize to the base type and let Jackson resolve the subtype via the `type` field:\n\n```java\nGeoJson geoJson = mapper.readValue(json, GeoJson.class);   // polymorphic root\nGeometry geometry = mapper.readValue(json, Geometry.class);  // geometry-only polymorphic\n```\n\n### Validation\n\nConstructors (used during deserialization) do **not** validate eagerly — this lets you inspect partially-populated\nobjects. Use `validate()` for detailed error information or `isValid()` for a quick check.\n\n```java\n// Quick boolean check\nGeoJson geoJson = mapper.readValue(json, GeoJson.class);\nboolean valid = geoJson.isValid();\n\n// Detailed validation result\nValidationResult result = geoJson.validate();\n\nif (result.hasErrors()) {\n    result.getErrors().forEach(error -\u003e\n        System.out.printf(\"Field: %-30s Key: %-40s Message: %s%n\",\n            error.getField(), error.getKey(), error.getMessage())\n    );\n}\n```\n\nStable validation error keys you can rely on in code:\n\n| Key                                     | Meaning                                       |\n|-----------------------------------------|-----------------------------------------------|\n| `type.invalid`                          | `type` field is missing or wrong              |\n| `coordinates.invalid.empty`             | `coordinates` is null or empty                |\n| `coordinates.latitude.invalid`          | latitude is out of the valid range            |\n| `coordinates.longitude.invalid`         | longitude is out of the valid range           |\n| `coordinates.invalid.minimum.positions` | not enough positions (e.g., polygon ring \u003c 4) |\n| `coordinates.invalid.ring.closed`       | polygon ring is not closed (first ≠ last)     |\n| `geometries.invalid.nested.geometry`    | `GeometryCollection` contains another one     |\n\n#### Fail-fast with factory methods\n\n```java\ntry {\n    // Latitude 999 is out of range → throws immediately\n    Point invalid = Point.of(102.0, 999.0);\n} catch (GeoJsonValidationException ex) {\n    // handle validation failure\n}\n```\n\n---\n\n## API Reference\n\n### Class Hierarchy\n\n```\nGeoJson (sealed)\n├── Geometry (sealed)\n│   ├── Point\n│   ├── LineString\n│   ├── Polygon\n│   ├── MultiPoint\n│   ├── MultiLineString\n│   ├── MultiPolygon\n│   └── GeometryCollection\n├── Feature\n└── FeatureCollection\n```\n\n### Key Types\n\n| Type                         | Description                                                  |\n|------------------------------|--------------------------------------------------------------|\n| `GeoJson`                    | Sealed root; Jackson polymorphism resolved via `type`        |\n| `Geometry`                   | Sealed base for all geometry types                           |\n| `Position`                   | Longitude / latitude / optional altitude coordinate tuple    |\n| `PolygonCoordinates`         | Enforces ring rules (≥ 4 positions, closed)                  |\n| `Validatable`                | Interface providing `validate()`, `isValid()`, `hasErrors()` |\n| `ValidationResult`           | Holds a set of `ValidationError` instances                   |\n| `GeoJsonValidationException` | Thrown by factory methods on invalid input                   |\n\n---\n\n## Examples\n\nA runnable Spring MVC example is available in [`examples/spring-mvc-example`](examples/spring-mvc-example). It\ndemonstrates:\n\n- **Echo endpoint** — round-trip serialization of any `GeoJson` object\n- **Validation endpoint** — returns `ValidationResult` as JSON\n- **CRUD endpoint** — persists and retrieves `GeoJson` using JPA + H2\n\n---\n\n## Build \u0026 Development\n\n```bash\n# Run tests only\nmvn test\n\n# Full build including Checkstyle\nmvn verify\n\n# With code-coverage report\nmvn -Pcoverage verify\n\n# Apply OpenRewrite recipes (license headers, static-analysis fixes …)\nmvn -Popen-rewrite process-sources\n\n# Dry-run OpenRewrite (check without applying)\nmvn -Popen-rewrite prepare-package\n```\n\nCode style is enforced by Checkstyle (`config/checkstyle/geojson4j_checks.xml`):\n\n- Google-style base\n- 160-character line limit\n- No wildcard imports\n\n---\n\n## Contributing\n\nContributions are very welcome! Here's how to get started:\n\n1. **Fork** the repository\n2. **Create** a feature branch: `git checkout -b feature/my-feature`\n3. **Commit** your changes following the [Conventional Commits](https://www.conventionalcommits.org/) format\n4. **Push** the branch: `git push origin feature/my-feature`\n5. **Open a Pull Request** — the CI pipeline will run automatically\n\nPlease open an issue on [GitHub Issues](https://github.com/nramc/geojson4j/issues) to report bugs or request features\nbefore starting a large change.\n\n### Adding a New GeoJSON Type\n\nFollow the pattern established by existing types:\n\n1. Add the type constant in `GeoJsonType.java`\n2. Register `@JsonSubTypes` entries in both `GeoJson` and `Geometry`\n3. Implement the class: no-arg constructor + `@JsonCreator` constructor + `of(...)` factory + `validate()` +\n   `equals/hashCode/toString`\n4. Add tests covering serialization, base-type deserialization, invalid states, and eager-validation exceptions\n\n---\n\n## License\n\nDistributed under the **Apache License 2.0**. See [`LICENSE`](./LICENSE) for full text.\n\n---\n\n## Acknowledgements\n\n| Tool                                            | Purpose                              |\n|-------------------------------------------------|--------------------------------------|\n| [Jackson](https://github.com/FasterXML/jackson) | JSON serialization / deserialization |\n| [SonarCloud](https://sonarcloud.io/)            | Static analysis \u0026 quality gate       |\n| [OpenRewrite](https://docs.openrewrite.org/)    | Automated code refactoring           |\n| [Renovate](https://docs.renovatebot.com/)       | Automated dependency updates         |\n\n---\n\n## Contact\n\n**Ramachandran Nellaiyappan**\n\n[![GitHub](https://img.shields.io/badge/GitHub-nramc-181717?logo=github)](https://github.com/nramc)\n[![LinkedIn](https://img.shields.io/badge/LinkedIn-connect-0A66C2?logo=linkedin)](https://www.linkedin.com/in/ramachandran-nellaiyappan/)\n[![Email](https://img.shields.io/badge/Email-ramachandrannellai%40gmail.com-D14836?logo=gmail)](mailto:ramachandrannellai@gmail.com)\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n⭐ If you find this project useful, please give it a star — it helps a lot!\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnramc%2Fgeojson4j","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnramc%2Fgeojson4j","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnramc%2Fgeojson4j/lists"}