You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何反序列化带额外分页属性的NTS FeatureCollection?

问题描述

调用第三方API返回的GeoJSON FeatureCollection 包含游标分页所需的额外属性(如links、numberReturned、timeStamp),但NetTopologySuite(NTS)自带的FeatureCollection类没有这些属性。使用GeoJsonConverterFactory可以正常反序列化地理特征部分,但尝试单独反序列化分页属性到自定义POCO时,属性值均为null,无法获取分页信息。

提供的代码示例中,两次反序列化分别处理FeatureCollection和FeatureCollectionResponse,但分页属性未被正确解析。


解决方案

方法一:自定义包装类复用NTS序列化逻辑

创建包含额外分页属性的包装类,内嵌FeatureCollection,利用NTS转换器处理地理数据,同时保留分页属性。

步骤1:定义包装类

public class Link
{
    public string Rel { get; set; }
    public string Type { get; set; }
    public string Title { get; set; }
    public string Href { get; set; }
}

public class PaginatedFeatureCollection
{
    // 额外分页属性
    public DateTime TimeStamp { get; set; }
    public Link[] Links { get; set; }
    public int NumberReturned { get; set; }
    
    // NTS核心FeatureCollection,对应GeoJSON的features数组
    public FeatureCollection Features { get; set; }
}

步骤2:反序列化配置与调用

var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
serializerOptions.Converters.Add(new GeoJsonConverterFactory());

var paginatedResult = JsonSerializer.Deserialize<PaginatedFeatureCollection>(json, serializerOptions);

// 访问地理特征
Console.WriteLine($"第一个特征ID: {paginatedResult.Features[0].Id}");
// 访问分页信息
Console.WriteLine($"返回数量: {paginatedResult.NumberReturned}");
Console.WriteLine($"下一页链接: {paginatedResult.Links.First(l => l.Rel == "next")?.Href}");

方法二:自定义JsonConverter扩展FeatureCollection

编写自定义转换器,先提取分页属性,再委托NTS转换器处理核心FeatureCollection,将额外属性存入FeatureCollection的ExtendedProperties字典。

步骤1:编写自定义转换器

public class FeatureCollectionWithPaginationConverter : JsonConverter<FeatureCollection>
{
    private readonly GeoJsonConverterFactory _ntsConverterFactory = new();

    public override FeatureCollection Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 读取完整JSON文档以提取额外属性
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;

        // 解析分页属性
        var timeStamp = root.GetProperty("timeStamp").GetDateTime();
        var links = JsonSerializer.Deserialize<Link[]>(root.GetProperty("links").GetRawText(), options);
        var numberReturned = root.GetProperty("numberReturned").GetInt32();

        // 委托NTS转换器反序列化核心FeatureCollection
        var featureCollection = JsonSerializer.Deserialize<FeatureCollection>(root.GetRawText(), options);

        // 将额外属性存入ExtendedProperties
        featureCollection.ExtendedProperties["timeStamp"] = timeStamp;
        featureCollection.ExtendedProperties["links"] = links;
        featureCollection.ExtendedProperties["numberReturned"] = numberReturned;

        return featureCollection;
    }

    public override void Write(Utf8JsonWriter writer, FeatureCollection value, JsonSerializerOptions options)
    {
        // 序列化时复用NTS逻辑,可按需扩展
        _ntsConverterFactory.GetConverter(typeof(FeatureCollection)).Write(writer, value, options);
    }
}

步骤2:使用自定义转换器

var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
// 替换默认NTS转换器为自定义转换器
serializerOptions.Converters.Add(new FeatureCollectionWithPaginationConverter());

var featureCollection = JsonSerializer.Deserialize<FeatureCollection>(json, serializerOptions);

// 从ExtendedProperties获取分页信息
var numberReturned = (int)featureCollection.ExtendedProperties["numberReturned"];
var links = (Link[])featureCollection.ExtendedProperties["links"];

Console.WriteLine($"返回数量: {numberReturned}");
Console.WriteLine($"下一页链接: {links.First(l => l.Rel == "next")?.Href}");

原代码问题说明

你之前两次反序列化失败的核心原因:

  1. 第二次反序列化未传入包含NTS转换器的serializerOptions,且默认配置未开启驼峰命名匹配(JSON中是links,类属性是Links);
  2. 重复反序列化同一JSON字符串效率较低,且容易出现流读取问题。

如果要保留两次反序列化的方式,需给第二次反序列化传入相同配置:

var paginationInformation = JsonSerializer.Deserialize<FeatureCollectionResponse>(json, serializerOptions);

但仍推荐使用前两种更高效的方案。


内容的提问来源于stack exchange,提问作者David H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 12:05:54