/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Linq; using MongoDB.Bson; using MongoDB.Bson.IO; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; namespace MongoDB.Driver.GeoJsonObjectModel.Serializers { /// /// Represents a serializer for a GeoJsonBoundingBox value. /// /// The type of the coordinates. public class GeoJsonBoundingBoxSerializer : ClassSerializerBase> where TCoordinates : GeoJsonCoordinates { // private fields private readonly IBsonSerializer _coordinatesSerializer = BsonSerializer.LookupSerializer(); // protected methods /// /// Deserializes a value. /// /// The deserialization context. /// The deserialization args. /// The value. protected override GeoJsonBoundingBox DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args) { var bsonReader = context.Reader; var flattenedArray = BsonArraySerializer.Instance.Deserialize(context); if ((flattenedArray.Count % 2) != 0) { throw new FormatException("Bounding box array does not have an even number of values."); } var half = flattenedArray.Count / 2; // create a dummy document with a min and a max and then deserialize the min and max coordinates from there var document = new BsonDocument { { "min", new BsonArray(flattenedArray.Take(half)) }, { "max", new BsonArray(flattenedArray.Skip(half)) } }; using (var documentReader = new BsonDocumentReader(document)) { var documentContext = BsonDeserializationContext.CreateRoot(documentReader); documentReader.ReadStartDocument(); documentReader.ReadName("min"); var min = _coordinatesSerializer.Deserialize(documentContext); documentReader.ReadName("max"); var max = _coordinatesSerializer.Deserialize(documentContext); documentReader.ReadEndDocument(); return new GeoJsonBoundingBox(min, max); } } /// /// Serializes a value. /// /// The serialization context. /// The serialization args. /// The value. protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, GeoJsonBoundingBox value) { var bsonWriter = context.Writer; // serialize min and max to a dummy document and then flatten the two arrays and serialize that var document = new BsonDocument(); using (var documentWriter = new BsonDocumentWriter(document)) { var documentContext = BsonSerializationContext.CreateRoot(documentWriter); documentWriter.WriteStartDocument(); documentWriter.WriteName("min"); _coordinatesSerializer.Serialize(documentContext, value.Min); documentWriter.WriteName("max"); _coordinatesSerializer.Serialize(documentContext, value.Max); documentWriter.WriteEndDocument(); } var flattenedArray = new BsonArray(); flattenedArray.AddRange(document["min"].AsBsonArray); flattenedArray.AddRange(document["max"].AsBsonArray); BsonArraySerializer.Instance.Serialize(context, flattenedArray); } } }