Skip to content

Commit

Permalink
Allow "foreign members" in a GeoJSON Objects
Browse files Browse the repository at this point in the history
  • Loading branch information
mamantoha committed Mar 23, 2020
1 parent 4950058 commit f20a377
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 1 deletion.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This library contains:

- Functions for encoding and decoding GeoJSON formatted data
- Classes for all GeoJSON Objects
- Allow "foreign members" in a GeoJSON Objects

## Installation

Expand Down Expand Up @@ -388,6 +389,34 @@ feature_collection.to_json
}
```

## Foreign Members

For example, in the `Pont` object shown below

```json
{
"type": "Point",
"coordinates": [-80.1347334, 25.7663562],
"title": "Example Point"
}
```

the name/value pair of `"title": "Example Point"` is a foreign member.
GeoJSON semantics do not apply to foreign members and their descendants, regardless of their names and values.
If the GeoJSON type include foreign members, this properties in the JSON document will be stored in a `Hash(String, JSON::Any)`.
On serialization, any keys inside `json_unmapped` will be serialized and appended to the current json object.

```crystal
point = GeoJSON::Point.new([-80.1347334, 25.7663562])
json_unmapped = Hash(String, JSON::Any).new
json_unmapped["title"] = JSON::Any.new("Example Point")
point.json_unmapped = json_unmapped
```

## Contributing

1. Fork it (<https://github.com/geocrystal/geo_json/fork>)
Expand Down
35 changes: 35 additions & 0 deletions spec/feature_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ describe GeoJSON::Feature do
},
}.to_json

feature_with_foreign_members_json = {
"type" => "Feature",
"geometry" => {
"type" => "Point",
"coordinates" => point_coordinates,
},
"properties" => {
"prop0" => "value0",
},
"title" => "Example Feature",
}.to_json

describe "json parser" do
it "parses feture point json" do
feature = GeoJSON::Feature.from_json(feature_point_json)
Expand All @@ -55,6 +67,15 @@ describe GeoJSON::Feature do
polygon = feature.geometry.not_nil!.as(GeoJSON::Polygon)
polygon.coordinates.should be_a(Array(Array(GeoJSON::Coordinates)))
end

it "parses feture with foreign json member" do
feature = GeoJSON::Feature.from_json(feature_with_foreign_members_json)

feature.should be_a(GeoJSON::Feature)
feature.type.should eq("Feature")
feature.json_unmapped["title"].should eq("Example Feature")
feature.geometry.should be_a(GeoJSON::Point)
end
end

describe ".new" do
Expand Down Expand Up @@ -86,6 +107,20 @@ describe GeoJSON::Feature do
feature.properties.should eq(properties)
feature.id.should eq(1)
end

it "initialize Feature with foreign member" do
geometry = GeoJSON::Point.new(point_coordinates)
properties = {"prop0" => "value0"} of String => JSON::Any::Type

json_unmapped = Hash(String, JSON::Any).new
json_unmapped["title"] = JSON::Any.new("Example Feature")

feature = GeoJSON::Feature.new(geometry, properties)
feature.json_unmapped = json_unmapped

feature.geometry.should eq(geometry)
feature.to_json.should eq(feature_with_foreign_members_json)
end
end

describe "json object" do
Expand Down
1 change: 0 additions & 1 deletion spec/multi_polygon_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ describe GeoJSON::MultiPolygon do
polygon2 = GeoJSON::Polygon.new(ring2)

multi_polygon = GeoJSON::MultiPolygon.new([polygon1, polygon2])
puts multi_polygon.to_json

multi_polygon.should be_a(GeoJSON::MultiPolygon)
multi_polygon.type.should eq("MultiPolygon")
Expand Down
11 changes: 11 additions & 0 deletions spec/point_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ describe GeoJSON::Point do
point.to_json.should eq(point_json)
end

it "creates Point with foreign member" do
point = GeoJSON::Point.new(position)

json_unmapped = Hash(String, JSON::Any).new
json_unmapped["title"] = JSON::Any.new("Example Point")

point.json_unmapped = json_unmapped

point.to_json.should eq("{\"type\":\"Point\",\"coordinates\":[-80.1347334,25.7663562],\"title\":\"Example Point\"}")
end

it "raises an exception if coordinates are invalid" do
expect_raises GeoJSON::Exception, "coordinates need to have have two or three elements" do
GeoJSON::Point.new(invalid_position)
Expand Down
1 change: 1 addition & 0 deletions src/geo_json/object.cr
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module GeoJSON
# * A GeoJSON object MAY have other members
abstract class Object
include JSON::Serializable
include JSON::Serializable::Unmapped

# All possible GeoJSON types.
alias Type = Point | MultiPoint | LineString | MultiLineString | Polygon | MultiPolygon
Expand Down

0 comments on commit f20a377

Please sign in to comment.