Предложения по созданию пользовательского сериализатора GeoJson с использованием JSON.NET?

Я буду пытаться создать библиотеку С# для сериализации объектов GeoJSON с помощью Json.NET (для сериализации) и GeoAPI.NET (для определения геометрии).

Я подумал о двух разных подходах к реализации сериализации, и я не знаю, какой из них лучше всего подходит. Это:

Подход 1 - Пользовательские атрибуты

Первый подход включает в себя создание нескольких настраиваемых атрибутов, которые могут быть применены к любому классу для изменения сериализации. Например, класс может быть оформлен так:

[GeoJsonFeature]
public class Building
{
   [GeoJsonId]
   public Guid Id { get; set; }
   [GeoJsonProperty]
   public string Name { get; set; }
   [GeoJsonProperty]
   public int Floorcount { get; set; }
   [GeoJsonGeometry]
   public GeoAPI.Geometries.IGeometry Geometry { get; set; }
}

Сериализация объекта будет таким же простым, как:

JsonNetResult jsonNetResult = new JsonNetResult();
jsonNetResult.Formatting = Formatting.Indented;
jsonNetResult.Data = building;
return jsonNetResult;

Преимущество такого подхода состоит в том, что любой бизнес-объект может быть превращен в объект GeoJSON, предполагая, что он обладает требуемыми свойствами (например, Geometry). Недостатком было бы то, что мне понадобилось бы создать несколько настраиваемых атрибутов для поддержки сериализации. Кроме того, это влияет на "смешение" бизнес-объекта.

Наконец, я еще не определил, возможен ли этот подход с JSON.NET, хотя кажется, что это будет.

Подход 2 - Пользовательский JsonConverter

Второй подход включает создание пользовательских преобразователей для различных типов. Например, у меня может быть GeoJsonConverter, что при передаче объекта определенного типа, скажем, Feature, создается объект GeoJSON. Это может выглядеть так:

public class GeoJsonFeatureConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer)
    {  
        // serializing code here 
    }

    public override void ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer)
    {  
        // deserializing code here 
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(Feature).IsAssignableFrom(objectType);
    }
}

Тогда я мог бы сериализовать GeoJson так:

JsonNetResult jsonNetResult = new JsonNetResult();
jsonNetResult.Formatting = Formatting.Indented;
jsonNetResult.SerializerSettings.Converters.Add(new GeoJsonFeatureConverter());
jsonNetResult.Data = building;

Преимущество в том, что это кажется более простым в создании. Я доказал, что этот подход возможен через очень простой прототип. Кроме того, класс Feature уже определен, если я ссылаюсь на NetTopologySuite.

Недостатком было бы то, что мои бизнес-объекты должны были быть сопоставлены с Feature перед сериализацией. Хотя это можно считать преимуществом, поскольку это может обеспечить естественную развязку между слоями. В обоих случаях определенно будет тесная связь с GeoAPI в обоих случаях и NetTopologySuite в дальнейшем. Думаю, я в порядке.

Мне известно о нескольких других сериализаторах GeoJson, таких как GeoJson.NET, однако мне нужен подход, который согласуется с Json.NET API, так как это наш сериализатор выбора.

Вы видите очевидные причины, по которым один подход был бы предпочтительнее другого? Возможно, есть другой подход, о котором я не знаю?

FYI, я склоняюсь к второму подходу. Похоже, что было бы проще реализовать и что оно будет более чистым в целом. Мне также нравится естественная граница между объектами домена и объектами GeoJson, которые он создавал.

Ответ 1

Лично я склоняюсь к первому выбору по простой причине. Если вы посмотрите на платформу .NET, там есть аналог вашей сериализации в пространстве имен System.Xml.Serialization. Там они делают почти то, что вы предлагаете в своем первом подходе.

Однако, если вам это не особенно нравится, я бы предложил третий подход: Напишите собственный форматирующий формат сериализации, внедряя System.Runtime.Serialization.IFormatter. Это дает вам возможность использовать стандартную сериализованную нотацию и механизмы для объектов (например, [Serializable] и ISerializable), но вы следуете хорошо распознанному шаблону, поэтому его легко распознать. Плюс в качестве дополнительного бонуса вы можете легко поддерживать другие формы сериализации (двоичные, мыльные, другие пользовательские форматы) в будущем, заменив реализацию IFormatter

Изменить: здесь пример: http://geekswithblogs.net/luskan/archive/2007/07/16/113956.aspx