Предложения о том, как создать собственный сериализатор GeoJson, используя JSON.NET? - PullRequest
10 голосов
/ 11 августа 2009

Я попытаюсь создать библиотеку 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 , однако я хотел бы использовать подход, совместимый с API Json.NET, так как это наш предпочтительный сериализатор.

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

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

1 Ответ

2 голосов
/ 15 августа 2009

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

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

Редактировать: вот пример: http://geekswithblogs.net/luskan/archive/2007/07/16/113956.aspx

...