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

Я попытаюсь создать библиотеку C# для сериализации объектов в 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, так как это наш предпочтительный сериализатор.

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

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


person Ryan Taylor    schedule 11.08.2009    source источник


Ответы (1)


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

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

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

person Hounshell    schedule 14.08.2009