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

.NET 8中使用System.Text.Json序列化空间点失败问题排查

问题

在Blazor 8服务端应用中序列化EF模型中的空间点字段CurrentHabitat.SiteLocation时失败。该字段对应MSSQL数据库的(geography,null)类型,模型是通过反向工程生成的。

序列化代码

var options = new JsonSerializerOptions
{
    Converters =
    {
        new MicrosoftSpatialGeoJsonConverter()
    },
    NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals,
    ReferenceHandler = ReferenceHandler.Preserve,
    MaxDepth=100
};

string thisLatLong = JsonSerializer.Serialize(CurrentHabitat.SiteLocation,options);

字段值详情

{POINT (-3.89695 55.99762)}
    Area: 0
    Boundary: {GEOMETRYCOLLECTION EMPTY}
    BoundaryDimension: False
    Centroid: {POINT (-3.89695 55.99762)}
    Coordinate: {(-3.89695, 55.99762)}
    CoordinateSequence: {((-3.89695, 55.99762))}
    Coordinates: {NetTopologySuite.Geometries.Coordinate[1]}
    Dimension: P
    Envelope: {POINT (-3.89695 55.99762)}
    EnvelopeInternal: {Env[-3.89695 : -3.89695, 55.99762 : 55.99762]}
    Factory: {GeometryFactory[PM=Floating, SRID=4326, CSFactory=CoordinateArraySequenceFactory, GeometryOverlay:Legacy]}
    GeometryType: "Point"
    InteriorPoint: {POINT (-3.89695 55.99762)}
    IsEmpty: false
    IsGeometryCollection: false
    IsRectangle: false
    IsSimple: true
    IsValid: true
    Length: 0
    M: NaN
    NumGeometries: 1
    NumPoints: 1
    OgcGeometryType: Point
    PointOnSurface: {POINT (-3.89695 55.99762)}
    PrecisionModel: {Floating}
    SRID: 4326
    SortIndex: Point
    UserData: null
    X: -3.89695
    Y: 55.99762
    Z: NaN

错误信息

{"Specified argument was out of the range of valid values. (Parameter 'X called on empty Point')"}

堆栈跟踪

at NetTopologySuite.Geometries.Point.get_X()
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.Serialize(Utf8JsonWriter writer, T& rootValue, Object rootValueBoxed)
   at System.Text.Json.JsonSerializer.WriteString[TValue](TValue& value, JsonTypeInfo`1 jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)
   at HabitatHub3.Pages.ShowPond.<onSaveClick>d__42.MoveNext() in C:\Users\Blahblah\source\repos\HabitatHub3\HabitatHub3\Pages\ShowPond.razor:line 371

解决方案

问题根源

你使用的MicrosoftSpatialGeoJsonConverter是针对Microsoft.Spatial类型(如DbGeography)设计的,但你的SiteLocation实际是NetTopologySuite(NTS)的Point类型,两者不兼容。序列化时JsonSerializer会尝试用默认转换器处理对象的嵌套属性(比如Boundary这个空的GeometryCollection),访问其内部空Point的X属性时触发错误。

修复步骤

  1. 替换为NTS专属的Json转换器
    先安装NetTopologySuite的Json序列化包:NetTopologySuite.IO.JsonSystemTextJson
    然后修改序列化配置:

    using NetTopologySuite.IO;
    
    var options = new JsonSerializerOptions
    {
        Converters = { new GeoJsonConverterFactory() },
        NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals,
        ReferenceHandler = ReferenceHandler.Preserve,
        MaxDepth=100
    };
    
    string thisLatLong = JsonSerializer.Serialize(CurrentHabitat.SiteLocation, options);
    
  2. 直接提取坐标序列化(临时方案)
    若只需要坐标值,可跳过完整对象序列化,直接输出符合GeoJSON格式的字符串:

    string thisLatLong = $"{{\"type\":\"Point\",\"coordinates\":[{CurrentHabitat.SiteLocation.X},{CurrentHabitat.SiteLocation.Y}]}}";
    
  3. 排除空属性序列化(可选)
    如果不想替换转换器,可在JsonSerializerOptions中添加DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,或给NTS类型的空属性手动添加[JsonIgnore]特性,但这种方法可靠性较低,仍可能触发内部属性访问错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 13:45:33