简体   繁体   中英

SignalR switching from NewtonsoftJsonProtocol to JsonProtocol throws System.Text.Json.JsonException: '{' is invalid after a value

In.Net 6, when trying to use SignalR with JsonProtocol (System.Text.Json), my client program throws the following exception

System.IO.InvalidDataException: Error reading JSON.
   ---> System.Text.Json.JsonException: '{' is invalid after a value. Expected either ',', '}', or ']'. Path: $ | LineNumber: 0 | BytePositionInLine: 4090

Code on server side:

services.AddSignalR()
    .AddJsonProtocol();

Code on client side:

conn = new HubConnectionBuilder()
        .WithUrl($"{_serverBaseAddress}mainHub", o =>
            {
                o.AccessTokenProvider = InitializeOrRefreshAccessTokenIfNeeded;
                o.Transports = HttpTransportType.WebSockets;
            }
        )
        .ConfigureLogging(logging =>
        {
            logging.AddConsole();
        })
        .AddJsonProtocol()
        .Build()

Note: everything works fine when using NewtonsoftJsonProtocol :

Code on server:

services.AddSignalR()
        .AddNewtonsoftJsonProtocol(opts =>
        {
            opts.PayloadSerializerSettings.TypeNameHandling = TypeNameHandling.All;
        });

Code on client:

conn = new HubConnectionBuilder()
        .WithUrl($"{_serverBaseAddress}mainHub", o =>
            {
                o.AccessTokenProvider = InitializeOrRefreshAccessTokenIfNeeded;
                o.Transports = HttpTransportType.WebSockets;
            }
        )
        .ConfigureLogging(logging =>
        {
            logging.AddConsole();
        })
        .AddNewtonsoftJsonProtocol(
        opts =>
            opts.PayloadSerializerSettings.TypeNameHandling = TypeNameHandling.All
        )
        .Build();

There is a difference, with NewtonsoftJson I specify TypeNameHandling.All but I do not know any equivalent for System.Text.Json.

Why not just keep Newtonsoft.Json? I would like to use source generators and specify a SerializerContext like below:

.AddJsonProtocol(options =>
{
    options.PayloadSerializerOptions.AddContext<MyJsonSerializerContext>();
});

which I believe I cannot do with NewtonsoftJson

As it turned out, switching from Newtonsoft.Json to System.Text.Json is not as simple as just switching protocols in the configuration.

There is this page from Microsoft that describes the key differences between the 2 and helps with the migration: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to?pivots=dotnet-6-0

As they explain, in some scenarios it will not be possible to move to System.Text.Json .

So in my case, I was looking at errors on the client but actually, the server was throwing a cycling error like this one: How to JSON serialize without cyclic error Replacing [IgnoreDataMember] by [JsonIgnore] fixes the issue.

Also TypeNameHandling.All which I was using in Newtonsoft.Json is not supported in System.Text.Json . I was using this setting because of polymorphic deserialization, but in this case, they propose to write custom converters as a workaround which I haven't tested yet: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to?pivots=dotnet-6-0#support-polymorphic-deserialization

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM