Skip to content

Commit

Permalink
Work on GeoJSON Convertes and Serializers (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
FObermaier committed Sep 12, 2016
1 parent b946c24 commit 243ede3
Show file tree
Hide file tree
Showing 14 changed files with 631 additions and 78 deletions.
Expand Up @@ -24,7 +24,10 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s

IAttributesTable attributes = value as IAttributesTable;
if (attributes == null)
{
writer.WriteNull();
return;
}

writer.WriteStartObject();
string[] names = attributes.GetNames();
Expand Down Expand Up @@ -120,41 +123,47 @@ private static object InternalReadJson(JsonReader reader, JsonSerializer seriali
if (reader.TokenType != JsonToken.StartObject)
throw new ArgumentException("Expected token '{' not found.");

// Advance reader
reader.Read();
AttributesTable attributesTable = new AttributesTable();
while (reader.TokenType == JsonToken.PropertyName)

AttributesTable attributesTable = null;
if (reader.TokenType != JsonToken.Null)
{
string attributeName = (string)reader.Value;
reader.Read();
object attributeValue;
if (reader.TokenType == JsonToken.StartObject)
{
// inner object
attributeValue = InternalReadJson(reader, serializer);
if (reader.TokenType != JsonToken.EndObject)
throw new ArgumentException("Expected token '}' not found.");
// read EndObject token
reader.Read();
}
else if (reader.TokenType == JsonToken.StartArray)
{
attributeValue = InternalReadJsonArray(reader, serializer);
//reader.Read(); // move to first item
//IList<object> array = new List<object>();
//do
//{
// object inner = InternalReadJson(reader, serializer);
// array.Add(inner);
// reader.Read(); // move to next item
//} while (reader.TokenType != JsonToken.EndArray);
//attributeValue = array;
}
else
attributesTable = new AttributesTable();
while (reader.TokenType == JsonToken.PropertyName)
{
attributeValue = reader.Value;
string attributeName = (string) reader.Value;
reader.Read();
object attributeValue;
if (reader.TokenType == JsonToken.StartObject)
{
// inner object
attributeValue = InternalReadJson(reader, serializer);
if (reader.TokenType != JsonToken.EndObject)
throw new ArgumentException("Expected token '}' not found.");
// read EndObject token
reader.Read();
}
else if (reader.TokenType == JsonToken.StartArray)
{
attributeValue = InternalReadJsonArray(reader, serializer);
//reader.Read(); // move to first item
//IList<object> array = new List<object>();
//do
//{
// object inner = InternalReadJson(reader, serializer);
// array.Add(inner);
// reader.Read(); // move to next item
//} while (reader.TokenType != JsonToken.EndArray);
//attributeValue = array;
}
else
{
attributeValue = reader.Value;
reader.Read();
}
attributesTable.AddAttribute(attributeName, attributeValue);
}
attributesTable.AddAttribute(attributeName, attributeValue);
}
// TODO: refactor to remove check when reading TopoJSON
if (reader.TokenType != JsonToken.EndObject)
Expand Down
Expand Up @@ -12,7 +12,11 @@ public class CoordinateConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WritePropertyName("coordinates");
if (value == null)
{
writer.WriteToken(JsonToken.Null);
return;
}

List<List<Coordinate[]>> coordinatesss = value as List<List<Coordinate[]>>;
if (coordinatesss != null)
Expand Down
Expand Up @@ -15,14 +15,17 @@ public class EnvelopeConverter : JsonConverter
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Envelope envelope = value as Envelope;
if (envelope == null) return;
if (envelope == null)
{
writer.WriteToken(null);
return;
}

writer.WritePropertyName("bbox");
writer.WriteStartArray();
writer.WriteValue(envelope.MinX.ToString(NumberFormatInfo.InvariantInfo));
writer.WriteValue(envelope.MinY.ToString(NumberFormatInfo.InvariantInfo));
writer.WriteValue(envelope.MaxX.ToString(NumberFormatInfo.InvariantInfo));
writer.WriteValue(envelope.MaxY.ToString(NumberFormatInfo.InvariantInfo));
writer.WriteValue(envelope.MinX);
writer.WriteValue(envelope.MinY);
writer.WriteValue(envelope.MaxX);
writer.WriteValue(envelope.MaxY);
writer.WriteEndArray();
}

Expand All @@ -32,19 +35,25 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
Debug.Assert((string)reader.Value == "bbox");
reader.Read(); // move to array start

JArray envelope = serializer.Deserialize<JArray>(reader);
Debug.Assert(envelope.Count == 4);
if (reader.TokenType != JsonToken.Null)
{
JArray envelope = serializer.Deserialize<JArray>(reader);
Debug.Assert(envelope.Count == 4);

double minX = Double.Parse((string) envelope[0], NumberFormatInfo.InvariantInfo);
double minY = Double.Parse((string) envelope[1], NumberFormatInfo.InvariantInfo);
double maxX = Double.Parse((string) envelope[2], NumberFormatInfo.InvariantInfo);
double maxY = Double.Parse((string) envelope[3], NumberFormatInfo.InvariantInfo);
double minX = Double.Parse((string) envelope[0], NumberFormatInfo.InvariantInfo);
double minY = Double.Parse((string) envelope[1], NumberFormatInfo.InvariantInfo);
double maxX = Double.Parse((string) envelope[2], NumberFormatInfo.InvariantInfo);
double maxY = Double.Parse((string) envelope[3], NumberFormatInfo.InvariantInfo);

Debug.Assert(minX <= maxX);
Debug.Assert(minY <= maxY);
Debug.Assert(minX <= maxX);
Debug.Assert(minY <= maxY);

reader.Read(); // move away from array end
return new Envelope(minX, maxX, minY, maxY);
}

reader.Read(); // move away from array end
return new Envelope(minX, maxX, minY, maxY);
return null;
}

public override bool CanConvert(Type objectType)
Expand Down
Expand Up @@ -21,23 +21,29 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s

FeatureCollection coll = value as FeatureCollection;
if (coll == null)
{
if (serializer.NullValueHandling == NullValueHandling.Ignore)
{
writer.WriteToken(null);
}
return;
}

writer.WriteStartObject();
writer.WritePropertyName("type");
writer.WriteValue(coll.Type);
writer.WritePropertyName("features");
serializer.Serialize(writer, coll.Features);
if (coll.CRS != null)
if (serializer.NullValueHandling == NullValueHandling.Include || coll.CRS != null)
{
writer.WritePropertyName("crs");
serializer.Serialize(writer, coll.CRS);
}
var bbox = coll.BoundingBox;
if (bbox != null)
if (serializer.NullValueHandling == NullValueHandling.Include || bbox != null)
{
writer.WritePropertyName("bbox");
serializer.Serialize(writer, new[] { bbox.MinX, bbox.MinY, bbox.MaxX, bbox.MaxY }, typeof(double[]));
serializer.Serialize(writer, bbox, typeof(Envelope));
}
writer.WriteEndObject();
}
Expand Down
Expand Up @@ -23,7 +23,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
if (serializer == null)
throw new ArgumentNullException("serializer");

IFeature feature = value as Feature;
var feature = value as IFeature;
if (feature == null)
return;

Expand All @@ -35,27 +35,33 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s

// Add the id here if present in attributes.
// It will be skipped in serialization of properties
if (feature.Attributes.Exists("id"))
if (feature.Attributes != null && feature.Attributes.Exists("id"))
{
var id = feature.Attributes["id"];
writer.WritePropertyName("id");
serializer.Serialize(writer, id);
}

// bbox (optional)
if (feature.BoundingBox != null)
if (serializer.NullValueHandling == NullValueHandling.Include || feature.BoundingBox != null)
{
writer.WritePropertyName("bbox");
serializer.Serialize(writer, feature.BoundingBox, typeof(Envelope));
}

// geometry
writer.WritePropertyName("geometry");
serializer.Serialize(writer, feature.Geometry);
if (serializer.NullValueHandling == NullValueHandling.Include || feature.Geometry != null)
{
writer.WritePropertyName("geometry");
serializer.Serialize(writer, feature.Geometry, typeof(IGeometry));
}

// properties
writer.WritePropertyName("properties");
serializer.Serialize(writer, feature.Attributes);
if (serializer.NullValueHandling == NullValueHandling.Include || feature.Attributes != null)
{
writer.WritePropertyName("properties");
serializer.Serialize(writer, feature.Attributes, typeof(IAttributesTable));
}

writer.WriteEndObject();
}
Expand Down Expand Up @@ -161,7 +167,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
/// </returns>
public override bool CanConvert(Type objectType)
{
return typeof(Feature).IsAssignableFrom(objectType);
return typeof(IFeature).IsAssignableFrom(objectType);
}
}
}
Expand Up @@ -23,7 +23,10 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
{
IGeometry geom = value as IGeometry;
if (geom == null)
{
writer.WriteNull();
return;
}

writer.WriteStartObject();

Expand All @@ -34,25 +37,43 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
switch (geomType)
{
case GeoJsonObjectType.Point:
serializer.Serialize(writer, geom.Coordinate);
if (serializer.NullValueHandling == NullValueHandling.Include || geom.Coordinate != null)
{
writer.WritePropertyName("coordinates");
serializer.Serialize(writer, geom.Coordinate);
}
break;
case GeoJsonObjectType.LineString:
case GeoJsonObjectType.MultiPoint:
serializer.Serialize(writer, geom.Coordinates);
var linealCoords = geom.Coordinates;
if (serializer.NullValueHandling == NullValueHandling.Include || linealCoords != null)
{
writer.WritePropertyName("coordinates");
serializer.Serialize(writer, linealCoords);
}
break;
case GeoJsonObjectType.Polygon:
IPolygon poly = geom as IPolygon;
Debug.Assert(poly != null);
serializer.Serialize(writer, PolygonCoordinates(poly));
var polygonCoords = PolygonCoordinates(poly);
if (serializer.NullValueHandling == NullValueHandling.Include || polygonCoords != null)
{
writer.WritePropertyName("coordinates");
serializer.Serialize(writer, polygonCoords);
}
break;

case GeoJsonObjectType.MultiPolygon:
IMultiPolygon mpoly = geom as IMultiPolygon;
Debug.Assert(mpoly != null);
List<List<Coordinate[]>> list = new List<List<Coordinate[]>>();
var list = new List<List<Coordinate[]>>();
foreach (IPolygon mempoly in mpoly.Geometries)
list.Add(PolygonCoordinates(mempoly));
serializer.Serialize(writer, list);
if (serializer.NullValueHandling == NullValueHandling.Include || list.Count > 0)
{
writer.WritePropertyName("coordinates");
serializer.Serialize(writer, list);
}
break;

case GeoJsonObjectType.GeometryCollection:
Expand All @@ -64,7 +85,11 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
List<Coordinate[]> coordinates = new List<Coordinate[]>();
foreach (IGeometry geometry in ((IGeometryCollection)geom).Geometries)
coordinates.Add(geometry.Coordinates);
serializer.Serialize(writer, coordinates);
if (serializer.NullValueHandling == NullValueHandling.Include || coordinates.Count > 0)
{
writer.WritePropertyName("coordinates");
serializer.Serialize(writer, coordinates);
}
break;
}

Expand Down
Expand Up @@ -19,7 +19,10 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s

ICRSObject crs = value as ICRSObject;
if (crs == null)
{
writer.WriteToken(JsonToken.Null);
return;
}

writer.WriteStartObject();
writer.WritePropertyName("type");
Expand Down
Expand Up @@ -10,6 +10,39 @@ namespace NetTopologySuite.IO
/// </summary>
public class GeoJsonSerializer : JsonSerializer
{
public new static JsonSerializer CreateDefault()
{
var s = JsonSerializer.CreateDefault();
AddGeoJsonConverters(s, GeometryFactory.Default);
return s;
}

public static JsonSerializer Create(IGeometryFactory factory)
{
return Create(new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}, factory);
}

public static JsonSerializer Create(JsonSerializerSettings settings, IGeometryFactory factory)
{
var s = JsonSerializer.Create(settings);
AddGeoJsonConverters(s, factory);
return s;
}

private static void AddGeoJsonConverters(JsonSerializer s, IGeometryFactory factory)
{
var c = s.Converters;
c.Add(new ICRSObjectConverter());
c.Add(new FeatureCollectionConverter());
c.Add(new FeatureConverter());
c.Add(new AttributesTableConverter());
c.Add(new GeometryConverter(factory));
c.Add(new GeometryArrayConverter());
c.Add(new CoordinateConverter());
c.Add(new EnvelopeConverter());

}

/// <summary>
/// Initializes a new instance of the <see cref="GeoJsonSerializer"/> class.
/// </summary>
Expand Down

0 comments on commit 243ede3

Please sign in to comment.