Tom
Tom

Reputation: 8681

The collection type 'Newtonsoft.Json.Linq.JObject' is not supported

I have written an endpoint in .netcore 3.0 to return data but which ultimately throws the following error in the controller.

The error happens on line

return Ok(cityResponses);

I can see the data prior to executing this line

System.NotSupportedException: The collection type 'Newtonsoft.Json.Linq.JObject' is not supported.
   at System.Text.Json.JsonPropertyInfoNotNullable`4.GetDictionaryKeyAndValueFromGenericDictionary(WriteStackFrame& writeStackFrame, String& key, Object& value)
   at System.Text.Json.JsonPropertyInfo.GetDictionaryKeyAndValue(WriteStackFrame& writeStackFrame, String& key, Object& value)
   at System.Text.Json.JsonSerializer.HandleDictionary(JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, WriteStack& state)
   at System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, Object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|21_0(ResourceInvoker invoker, IActionResult result)

Controller

[HttpGet]
        [Route("cities")]
        public async Task<IActionResult> Cities()
        {
            var cities = await _cityInfoService.GetCities();

            var cityResponses =  MapCityResponse(cities);

            return Ok(cityResponses);
        }

Upvotes: 3

Views: 6242

Answers (1)

poke
poke

Reputation: 388023

The error message already gives you some hint here:

System.NotSupportedException: The collection type 'Newtonsoft.Json.Linq.JObject' is not supported. at System.Text.Json.JsonPropertyInfoNotNullable`4.GetDictionaryKeyAndValueFromGenericDictionary(WriteStackFrame& writeStackFrame, String& key, Object& value)

As you can see, there is some Newtonsoft.Json.Linq namespace, and a System.Text.Json namespace.

Starting with ASP.NET Core 3.0, the default serializer for JSON was changed from Newtonsoft.Json to the new serializer that is built into .NET Core: System.Text.Json. There is very detailed documentation on the differences between these two serializers and how to migrate your code to System.Text.Json. But the summary here is that System.Text.Json is—by design—more limited than Newtonsoft.Json and it will not be able to serialize directly from or to those JObject or JArray objects.

Fortunately, for applications that rely on the behavior of Newtonsoft.Json or otherwise require some of its flexibility, there is a way to reconfigure the ASP.NET Core application to continue using Newtonsoft.Json for JSON serialization.

To do that, you can follow the migration guide for ASP.NET Core 3.0. Essentially you will have to reference the NuGet package Microsoft.AspNetCore.Mvc.NewtonsoftJson and then call AddNewtonsoftJson() on the MVC builder in your ConfigureServices method. For example:

services.AddControllers()
    .AddNewtonsoftJson();

This will ensure that Newtonsoft.Json is used for all of the built-in JSON serialization, so your JObject and JArray usages should continue to work then.

Upvotes: 9

Related Questions