Skip to content

Commit

Permalink
provide extra converters
Browse files Browse the repository at this point in the history
for interoperability with DataFrames
  • Loading branch information
yeesian authored and yeesian committed Mar 8, 2015
1 parent 74ad34c commit 1ac8086
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 1 deletion.
27 changes: 27 additions & 0 deletions README.md
Expand Up @@ -87,6 +87,33 @@ julia> JSON.json(JSON.parse(osm_buildings)) # compared with the JSON parser
"{\"features\":[{\"geometry\":{\"coordinates\":[[[13.42634,52.49533],[13.4266,52.49524],[13.42619,52.49483],[13.42583,52.49495],[13.4259,52.49501],[13.42611,52.49494],[13.4264,52.49525],[13.4263,52.49529],[13.42634,52.49533]]],\"type\":\"Polygon\"},\"properties\":{\"height\":150,\"color\":\"rgb(255,200,150)\"},\"type\":\"Feature\"}],\"type\":\"FeatureCollection\"}"
```
- Convert a GeoJSON.FeatureCollection to a DataFrame
```julia
julia> GeoJSON.geojson2df(obj)
4x4 DataFrame
| Row | id |
|-----|----|
| 1 | NA |
| 2 | NA |
| 3 | NA |
| 4 | NA |

| Row | geometry |
|-----|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 | Polygon([[[13.4263,52.4953],[13.4266,52.4952],[13.4262,52.4948],[13.4258,52.495],[13.4259,52.495],[13.4261,52.4949],[13.4264,52.4952],[13.4263,52.4953],[13.4263,52.4953]]],#undef,#undef) |
| 2 | Polygon([[[13.4271,52.4954],[13.4275,52.4952],[13.4275,52.4952],[13.4274,52.4952],[13.4272,52.4952],[13.4269,52.495],[13.4271,52.4949],[13.4269,52.4947],[13.4265,52.4948],[13.4266,52.4949],[13.4268,52.4948],[13.4269,52.495],[13.4268,52.495],[13.4271,52.4954]]],#undef,#undef) |
| 3 | MultiPolygon([[[[13.4275,52.4944],[13.4279,52.4949],[13.428,52.4949],[13.4276,52.4944],[13.428,52.4943],[13.4285,52.4948],[13.4285,52.4948],[13.428,52.4942],[13.4275,52.4944]]],[[[13.428,52.495],[13.428,52.4949],[13.4284,52.4948],[13.4285,52.4948],[13.428,52.495]]]],#undef,#undef) |
| 4 | Polygon([[[13.4286,52.4948],[13.4292,52.4947],[13.4287,52.4941],[13.4285,52.4942],[13.429,52.4947],[13.4288,52.4947],[13.4284,52.4942],[13.4282,52.4943],[13.4286,52.4947],[13.4285,52.4948],[13.4286,52.4948]]],#undef,#undef) |

| Row | color | height |
|-----|--------------------|--------|
| 1 | "rgb(255,200,150)" | 150 |
| 2 | "rgb(180,240,180)" | 130 |
| 3 | "rgb(200,200,250)" | 120 |
| 4 | "rgb(150,180,210)" | 140 |
```
- Writes a compact (no extra whitespace or identation) JSON representation to the supplied IO.
```julia
Expand Down
1 change: 1 addition & 0 deletions REQUIRE
@@ -1,3 +1,4 @@
julia 0.3
JSON
DataFrames
Compat
2 changes: 1 addition & 1 deletion src/GeoJSON.jl
@@ -1,6 +1,6 @@
module GeoJSON

using JSON, Compat
using JSON, DataFrames, Compat

export
Point,
Expand Down
37 changes: 37 additions & 0 deletions src/parser.jl
Expand Up @@ -67,10 +67,47 @@ end

geojson2dict(obj::Nothing) = obj

function propertynames(obj::FeatureCollection)
columns = Set()
for feature in obj.features
if isdefined(feature, :properties)
for key in keys(feature.properties)
if in(key, columns)
continue
end
push!(columns, key)
end
end
end
[["id","geometry"],sort(collect(columns))]
end

function geojson2df(obj::FeatureCollection)
nrows = length(obj.features)
if nrows == 0
return DataFrame()
end
colnames = propertynames(obj)
ncols = length(colnames)
df = DataFrame([[Any, Geometry], repeat([Any], inner = [ncols-2])],
convert(Vector{Symbol}, colnames), nrows)
for i in 1:nrows
df[i, 1] = hasid(obj.features[i]) ? obj.features[i].id : NA
df[i, 2] = obj.features[i].geometry
if isdefined(obj.features[i], :properties)
for j in 3:ncols
df[i, j] = get(obj.features[i].properties, colnames[j], NA)
end
end
end
df
end

# String/File -> GeoJSON
parse(input; kwargs...) = dict2geojson(JSON.parse(input; kwargs...))
parsefile(filename; kwargs...) = dict2geojson(JSON.parsefile(filename; kwargs...))

# GeoJSON -> String/IO
geojson(obj::AbstractGeoJSON) = JSON.json(geojson2dict(obj))
geojson{T <: AbstractGeoJSON}(obj::Vector{T}) = JSON.json(map(geojson2dict, obj))
print(io::IO, obj::AbstractGeoJSON) = JSON.print(io, geojson2dict(obj))
21 changes: 21 additions & 0 deletions test/runtests.jl
Expand Up @@ -305,6 +305,13 @@ dict = GeoJSON.geojson2dict(feature)
@fact dict["id"] => "a7xlmuwyjioy"
@fact dict["type"] => "Feature"

df = GeoJSON.geojson2df(testobj)
@fact size(df) => (1,4)
@fact df[1,:STATE_ABBR] => "ZZ"
@fact df[1,:STATE_NAME] => "Top"
@fact typeof(df[1,:geometry]) => GeometryCollection


buildings = GeoJSON.parse(osm_buildings)
@fact typeof(buildings) => FeatureCollection
@fact GeoJSON.hasbbox(buildings) => false
Expand All @@ -323,12 +330,24 @@ feature = buildings.features[1]
@fact GeoJSON.hasbbox(feature) => false
@fact GeoJSON.hascrs(feature) => false

df = GeoJSON.geojson2df(buildings)
@fact size(df) => (4,4)
@fact df[:height] => [150,130,120,140]
@fact map(typeof, df[:geometry]) => [Polygon, Polygon, MultiPolygon, Polygon]
@fact df[:color] => ["rgb(255,200,150)",
"rgb(180,240,180)",
"rgb(200,200,250)",
"rgb(150,180,210)"]
@fact all(DataFrames.isna(df[:id])) => true

building_dict = GeoJSON.geojson2dict(buildings)
@fact typeof(building_dict) => Dict{String,Any}
@fact string(GeoJSON.parse(osm_buildings)) => string(GeoJSON.dict2geojson(building_dict))

@fact GeoJSON.geojson(buildings) =>
"""{\"features\":[{\"geometry\":{\"coordinates\":[[[13.42634,52.49533],[13.4266,52.49524],[13.42619,52.49483],[13.42583,52.49495],[13.4259,52.49501],[13.42611,52.49494],[13.4264,52.49525],[13.4263,52.49529],[13.42634,52.49533]]],\"type\":\"Polygon\"},\"properties\":{\"height\":150,\"color\":\"rgb(255,200,150)\"},\"type\":\"Feature\"},{\"geometry\":{\"coordinates\":[[[13.42706,52.49535],[13.42745,52.4952],[13.42745,52.4952],[13.42741,52.49516],[13.42717,52.49525],[13.42692,52.49501],[13.42714,52.49494],[13.42686,52.49466],[13.4265,52.49478],[13.42657,52.49486],[13.42678,52.4948],[13.42694,52.49496],[13.42675,52.49503],[13.42706,52.49535]]],\"type\":\"Polygon\"},\"properties\":{\"height\":130,\"color\":\"rgb(180,240,180)\"},\"type\":\"Feature\"},{\"geometry\":{\"coordinates\":[[[[13.42746,52.4944],[13.42794,52.49494],[13.42799,52.49492],[13.42755,52.49442],[13.42798,52.49428],[13.42846,52.4948],[13.42851,52.49478],[13.428,52.49422],[13.42746,52.4944]]],[[[13.42803,52.49497],[13.428,52.49493],[13.42844,52.49479],[13.42847,52.49483],[13.42803,52.49497]]]],\"type\":\"MultiPolygon\"},\"properties\":{\"height\":120,\"color\":\"rgb(200,200,250)\"},\"type\":\"Feature\"},{\"geometry\":{\"coordinates\":[[[13.42857,52.4948],[13.42918,52.49465],[13.42867,52.49412],[13.4285,52.49419],[13.42896,52.49465],[13.42882,52.49469],[13.42837,52.49423],[13.42821,52.49428],[13.42863,52.49473],[13.42853,52.49476],[13.42857,52.4948]]],\"type\":\"Polygon\"},\"properties\":{\"height\":140,\"color\":\"rgb(150,180,210)\"},\"type\":\"Feature\"}],\"type\":\"FeatureCollection\"}"""
@fact GeoJSON.geojson(buildings.features) =>
"""[{\"geometry\":{\"coordinates\":[[[13.42634,52.49533],[13.4266,52.49524],[13.42619,52.49483],[13.42583,52.49495],[13.4259,52.49501],[13.42611,52.49494],[13.4264,52.49525],[13.4263,52.49529],[13.42634,52.49533]]],\"type\":\"Polygon\"},\"type\":\"Feature\"},{\"geometry\":{\"coordinates\":[[[13.42706,52.49535],[13.42745,52.4952],[13.42745,52.4952],[13.42741,52.49516],[13.42717,52.49525],[13.42692,52.49501],[13.42714,52.49494],[13.42686,52.49466],[13.4265,52.49478],[13.42657,52.49486],[13.42678,52.4948],[13.42694,52.49496],[13.42675,52.49503],[13.42706,52.49535]]],\"type\":\"Polygon\"},\"type\":\"Feature\"},{\"geometry\":{\"coordinates\":[[[[13.42746,52.4944],[13.42794,52.49494],[13.42799,52.49492],[13.42755,52.49442],[13.42798,52.49428],[13.42846,52.4948],[13.42851,52.49478],[13.428,52.49422],[13.42746,52.4944]]],[[[13.42803,52.49497],[13.428,52.49493],[13.42844,52.49479],[13.42847,52.49483],[13.42803,52.49497]]]],\"type\":\"MultiPolygon\"},\"type\":\"Feature\"},{\"geometry\":{\"coordinates\":[[[13.42857,52.4948],[13.42918,52.49465],[13.42867,52.49412],[13.4285,52.49419],[13.42896,52.49465],[13.42882,52.49469],[13.42837,52.49423],[13.42821,52.49428],[13.42863,52.49473],[13.42853,52.49476],[13.42857,52.4948]]],\"type\":\"Polygon\"},\"type\":\"Feature\"}]"""

@fact GeoJSON.geojson(buildings) => JSON.json(JSON.parse(osm_buildings))
@fact building_dict => JSON.parse(osm_buildings)
Expand All @@ -347,3 +366,5 @@ feature = obj.features[1]
@fact length(feature.geometry.coordinates) => 1
@fact length(feature.geometry.coordinates[1]) => 38
@fact feature.geometry.coordinates[1][1] => feature.geometry.coordinates[1][end]


0 comments on commit 1ac8086

Please sign in to comment.