Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
airbreather opened this issue Apr 24, 2024 · 0 comments · May be fixed by #144

Comments

@airbreather
Copy link
Member

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant