Stripe v35.11.0
This breaks my dotnet core 3 project not using Newtonsoft.Json as the serializer, and I would assume anyone using System.Text.Json.
This is due to the JsonIgnore attribute from Newtonsoft not being used by System.Text.Json as it has it's own attribute.
There is some more information under this section on the migration guide: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to#conditionally-ignore-a-property
An unhandled exception has occurred while executing the request.
System.NotSupportedException: The collection type 'Newtonsoft.Json.Linq.JObject' on 'Stripe.Checkout.Session.RawJObject' 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.g__Awaited|29_0TFilter,TFilterAsync
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNextTFilter,TFilterAsync
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events)
at IdentityServer4.Hosting.MutualTlsTokenEndpointMiddleware.Invoke(HttpContext context, IAuthenticationSchemeProvider schemes)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
@sstalder Thanks for the report! ~We shipped a fix in 35.11.1 for that error so if you upgrade the error should go away!~
EDIT: Sorry it looks like your issue is different and we're looking into it.
Sorry I should of also gave an example. This happens when simply trying to serialize a Session object from a controller.
return Json(session);
Thanks for the report @sstalder, and sorry for the trouble.
My take on the issue is that it's expected that StripeEntity objects cannot be reliably serialized with different JSON serialization libraries than the one used by the Stripe.net library itself (i.e. Newtonsoft.Json). We do provide clean abstractions to serialize and deserialize objects without having to worry about the underlying JSON library:
```c#
var e = // some StripeEntity object
var json = e.ToJson();
var deserialized = StripeEntity.FromJson(json);
That said, System.Text.Json is not just any "random" JSON library -- it looks like it's in a good place to become the new standard JSON library for modern .NET apps. We aren't quite ready to make the switch from Newtonsoft.Json to System.Text.Json in Stripe.net itself, though we may do so in the future.
In the meantime, I think you'd have to write a custom converter to be able to serialize `StripeEntity` objects using System.Text.Json. Something along these lines:
```c#
namespace YourApp
{
public class StripeEntityConverter : JsonConverter<StripeEntity>
{
public override StripeEntity Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
StripeEntity.FromJson(reader.GetString());
public override void Write(
Utf8JsonWriter writer,
StripeEntity stripeEntity,
JsonSerializerOptions options) =>
writer.WriteString(stripeEntity.ToJson());
}
}
Would that work for you?
I wasn't aware of the json methods you had, thank you for that. I think the converter is a good alternative in the mean time. I completely understand not 100% supporting a somewhat new json library. Thanks for the quick assistance!
Glad I could help. I'm going to keep this issue open for the time being, and we'll spend some time investigating other possible solutions -- at the very least, we can document this somewhere so users of System.Text.Json know what to expect.
If you could report here to confirm whether the custom converter solution works for you or not, I'd really appreciate it too.
It looks like the custom converter does work, if anyone needs to go that route in the meantime.
I've just run into this as well. Any update here?
Stripe API's return is a JSON object with sake_case properties.
services.AddControllersWithViews().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
});
@ob-stripe Thanks a lot for mentioning this! We just encountered the same problem in serialization and will try that custom json converter
Wouldn't it be a better idea to return the following from the controller action?
return Content(stripeEntity.ToJson(), "application/json");
This way it would keep working even if/when Stripe.net migrates to System.Text.Json
Hi, I think I am having a similar issue. Is there any updates on this? I have a net core 5 site using Microsoft.AspNetCore.Mvc.NewtonsoftJson
Trying to read the json posted via webhook which used to work on core 3.1
var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
Event stripeEvent = EventUtility.ParseEvent(json, true);
I get:
Object reference not set to an instance of an object.
This exception was originally thrown at this call stack:
Stripe.Infrastructure.EventConverter.ReadJson(Newtonsoft.Json.JsonReader, System.Type, object, Newtonsoft.Json.JsonSerializer)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(Newtonsoft.Json.JsonConverter, Newtonsoft.Json.JsonReader, System.Type, object)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(Newtonsoft.Json.JsonReader, System.Type, bool)
@joffnerd , The json you are trying to parse probably not doesn't have "object": "event", as a property. That was my proble and using the right Json fixed my issue. The id should begin with "evt_".
Most helpful comment
Thanks for the report @sstalder, and sorry for the trouble.
My take on the issue is that it's expected that
StripeEntityobjects cannot be reliably serialized with different JSON serialization libraries than the one used by the Stripe.net library itself (i.e. Newtonsoft.Json). We do provide clean abstractions to serialize and deserialize objects without having to worry about the underlying JSON library:```c#
var e = // some StripeEntity object
var json = e.ToJson();
var deserialized = StripeEntity.FromJson(json);
Would that work for you?