C# · 12月 27, 2021

c# – 关于如何使用JSON.NET创建自定义GeoJson序列化程序的建议?

我将尝试创建一个C#库,以使用 Json.NET(序列化)和 GeoAPI.NET(用于几何定义)将对象序列化为 GeoJSON.

我已经考虑了两种不同的序列化实现方法,我不清楚哪一种是最好的方法.他们是:

方法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对象,假设它具有必需的属性(例如,几何).缺点是我需要创建一些自定义属性来支持序列化.此外,这也影响了业务对象的“混乱”.

最后,我还没有确定这个方法是否可能与JSON.NET,虽然它似乎是.

方法2 – 自定义JsonConverter

第二种方法涉及为各种类型创建自定义转换器.例如,我可能有一个GeoJsonConverter,当传递给定类型的对象时,说“功能”,将创建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;

这里的优点是,这似乎更容易创建.我已经证明,这种方法可以通过一个非常简单的原型.另外,如果链接到NetTopologySuite,则Feature类已经被定义.

缺点是我的业务对象需要在序列化之前映射到特性.虽然这可能被认为是一个优点,因为这可能会提供层之间的自然去耦.在这两种情况下,GeoAPI和NetTopologySuite肯定会紧密相连.我觉得我没事

我知道可以使用其他几个GeoJson序列化程序,例如GeoJson.NET,但是我想要一种与Json.NET API一致的方法,因为这是我们选择的序列化程序.

你看到有什么明显的原因,为什么一种方法比另一种方法更优先?也许还有另一种我不知道的方法?

我倾向于第二种方法.它似乎更容易实施,而且整体上会更加清洁.我也碰巧喜欢域创建对象和GeoJson对象之间的自然边界.

解决方法 我个人倾向于第一选择,原因很简单.如果您查看.NET框架,则可以在System.Xml.Serialization命名空间中对序列化进行模拟.在那里,他们几乎完全按照你第一种方式提出的建议.

但是,如果您不是特别喜欢,我建议第三种方法:编写一个自定义序列化格式化程序,实现System.Runtime.Serialization.Formatter.这使您能够为对象(如[Serializable]和ISerializable)使用标准的序列化符号和机制,但是您遵循一个公认的模式,便于识别.另外,您可以通过交换您的IFormatter实现轻松支持其他形式的序列化(二进制,肥皂,其他自定义格式)

编辑:这里是一个例子:http://geekswithblogs.net/luskan/archive/2007/07/16/113956.aspx