Skip to content

Exception thrown when trying to deserialize a Feature, FeatureCollection, or Geometry with unrecognized properties during a partial read #143

@airbreather

Description

@airbreather

Fix incoming after I'm done with work for the day...

Repro

Found when deserializing objects from a chunked stream, but it's easy enough to reproduce with everything in-memory.

Program.cs

using System.Text;
using System.Text.Json;

using NetTopologySuite.Features;
using NetTopologySuite.Geometries;
using NetTopologySuite.IO.Converters;

JsonSerializerOptions options = new() { Converters = { new GeoJsonConverterFactory() } };

(Type NtsType, string Json)[] fails =
[
    (typeof(FeatureCollection[]), """
    { "type": "FeatureCollection", "_other": { } }
    """),

    (typeof(IFeature[]), """
    { "type": "Feature", "_other": { } }
    """),

    (typeof(Point[]), """
    { "type": "Point", "_other": { }, "coordinates": null }
    """),
];

for (int i = 0; i < fails.Length; i++)
{
    byte[] payload = Encoding.UTF8.GetBytes(fails[i].Json);
    using OneByOneStream s = new();
    s.WriteByte((byte)'[');
    s.Write(payload);
    for (int j = 0; j < 500; j++)
    {
        s.WriteByte((byte)',');
        s.Write(payload);
    }

    s.WriteByte((byte)']');
    s.Position = 0;
    try
    {
        _ = JsonSerializer.Deserialize(s, fails[i].NtsType, options);
        Console.Error.WriteLine("No error!");
    }
    catch (JsonException ex)
    {
        Console.Error.WriteLine($"{fails[i].Json}:");
        Console.Error.WriteLine($"{new string(' ', (int)ex.BytePositionInLine!.Value)}^");
        Console.Error.WriteLine($"    {ex.Message}");
        Console.Error.WriteLine($"    ->    {ex.InnerException?.Message}");
        Console.Error.WriteLine();
    }
}

internal sealed class OneByOneStream : MemoryStream
{
    public override int Read(Span<byte> buffer) => base.Read(buffer[..Math.Min(buffer.Length, 1)]);
    public override int Read(byte[] buffer, int offset, int count) => base.Read(buffer, offset, Math.Min(count, 1));
}

ConsoleApp0.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="NetTopologySuite.IO.GeoJSON4STJ" Version="4.0.0" />
  </ItemGroup>

</Project>

Sample output

{ "type": "FeatureCollection", "_other": { } }:
                                           ^
    The JSON value could not be converted to NetTopologySuite.Features.FeatureCollection. Path: $[0] | LineNumber: 0 | BytePositionInLine: 43.
    ->    Cannot skip tokens on partial JSON. Either get the whole payload and create a Utf8JsonReader instance where isFinalBlock is true or call TrySkip.

{ "type": "Feature", "_other": { } }:
                                 ^
    The JSON value could not be converted to NetTopologySuite.Features.IFeature. Path: $[0] | LineNumber: 0 | BytePositionInLine: 33.
    ->    Cannot skip tokens on partial JSON. Either get the whole payload and create a Utf8JsonReader instance where isFinalBlock is true or call TrySkip.

{ "type": "Point", "_other": { }, "coordinates": null }:
                               ^
    The JSON value could not be converted to NetTopologySuite.Geometries.Point. Path: $[0] | LineNumber: 0 | BytePositionInLine: 31.
    ->    Cannot skip tokens on partial JSON. Either get the whole payload and create a Utf8JsonReader instance where isFinalBlock is true or call TrySkip.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions