Azure-functions-host: Add Config to set output serializer to System.Text.Json

Created on 12 Jan 2020  路  12Comments  路  Source: Azure/azure-functions-host

What problem would the feature you're requesting solve? Please describe.

Solves the problem that input serializer and output serializer are different.
Function v3 uses System.Text.Json as input serializer and Newtonsoft.Json as output serializer. (#5299)

When sharing a Domain Model with an ASP.NET Core application, different serializers can cause compatibility issues.

Describe the solution you'd like

I need to change the output serializer to System.Text.Json.

Describe alternatives you've considered

There is a way to configure all applications to use Newtonsoft.Json.
However, it does not match the current trend of .NET Core.

Additional context

https://github.com/Azure/azure-functions-host/blob/v3.x/src/WebJobs.Script.WebHost/WebHostServiceCollectionExtensions.cs#L75

Most helpful comment

I'm having an issue with this as well (https://github.com/Azure/azure-functions-host/issues/5203#issuecomment-667859103).

I believe it is impossible to use System.Text.Json when

  • returning an OkObjectResult,
  • when using the built-in deserialization of trigger input

This is annoying because projects shared between an asp.net core project and an azure functions project will have to "live in 2 worlds".

Imagine you want to set [JsonConverter(typeof(JsonStringEnumConverter))] on a data model enum (using System.Text.Json) and you want to use that in Azure Functions, it's a no go

All 12 comments

Thanks @shibayan for opening the issue. Functions v3 uses Newtonsoft.Json for serializer at all times. Is there a place you saw System.Text.Json used for serializing?

Regardless of that, this sounds like a fair ask to use System.Text.Json. I am not sure the work that may be involved and if it's something we will be able to look at very soon.

Adding @fabiocav if he had any comment on this ask or priority.

cc: @brettsam (had a super brief chat on this offline)

@ankitkumarr Thank you for replying.
Yes. Changing the default output serializer to System.Text.Json also has compatibility issues, so I want it to be switchable in settings.

ASP.NET Core 3.0 (MVC / SignalR) uses System.Text.Json by default. Attributes such as JsonProperty and JsonIgnore are not compatible with each other, causing problems when sharing domain models.

@fabiocav @ankitkumarr

I actually came here to see if there was an issue covering a move to use STJ when auto-deserializing POCOs as part of an HttpTrigger, etc. but haven't found something encompassing _quite_ that just yet.

Would it be fair to write an issue that says we should remove usage of NJ in favor of STJ in v3? Folks that requires NJ for compatibility can then import the package (free of unification struggles, yay!) and continue on, but w/in Functions and as part of things that are auto serialized/deserialized we'd be using STJ.

If we don't have an issue like this I'm happy to capture one. I think it would quite heavily impact each first-party extension as well, but they could each get their own similar issue.

I'm also happy to help out w/ the effort if acceptable. Or perhaps this better fits as an issue for the Webjobs SDK repo?

@brandonh-msft the serialization is not the main issue, the binding support is. A large number of apps use JObject as the binding target type. Removing that in the 3.0 timeframe wasn't viable, and removing in a current major would be a breaking change for those apps.

This is also the only reason why runtime unification exists, but in the vast majority of cases, this should not present a problem, and you still have the flexibility to reference different versions internally.

Do you have a concrete example of a problem you're dealing with because of that behavior?

I am also currently running into the problem of needing to use a custom JsonConverter that's designed to work with System.Text.Json, but Azure Functions appears to enforce Newtonsoft with no way to override in Startup.Configure

I'm having an issue with this as well (https://github.com/Azure/azure-functions-host/issues/5203#issuecomment-667859103).

I believe it is impossible to use System.Text.Json when

  • returning an OkObjectResult,
  • when using the built-in deserialization of trigger input

This is annoying because projects shared between an asp.net core project and an azure functions project will have to "live in 2 worlds".

Imagine you want to set [JsonConverter(typeof(JsonStringEnumConverter))] on a data model enum (using System.Text.Json) and you want to use that in Azure Functions, it's a no go

Concerning "Function v3 uses System.Text.Json as input serializer and Newtonsoft.Json as output serializer." I have also observed this to be the case. This is confusing and IMO would have been much more logical if MS had stuck with one or the other.

I just ran into the same case. Will this get fixed with .NET5 for Azure Functions?

@stevo-knievo the model with the OOP worker for .NET 5 in functions is a bit different, but you have full control over the stack there.

@fabiocav thanks for your reply! I'm looking forward to using .NET5 together with Azure Functions.

I am having trouble with this as well. Internally using System.Text.Json, including custom converters and pocos, so far so good. When trying to return a JsonResult from a HttpTrigger I realized that it is using Newtonsoft (and thus wont take my JsonSerializerOptions)

is there any way I can work around this?

Same here, having an object in the model and System.Text.Json transforms this to "ValueKind" objects but then when serialized via OkObjectResult gives me a corrupt Value.
an easy sample is a bool object of false get transformed to a object : { "valueKind": 6 } Do I need to rewoke all this to NewtonSoft?

Sample Object Read from Cosmos via System.Text.Json
[ { "Name": "Enabled", "Value": false, "Type": "bool", "DefaultValue": true, "AllowedValues": [] }, { "Name": "Severity", "Value": "Low", "Type": "enum", "DefaultValue": "Medium", "AllowedValues": [ "Low", "Medium", "Warning", "Critical" ] } ]
Ends up like this when using OkObjectResult or JsonResult as return IActionResult it ends up like this, note the valueKind. And that breaks the consumer.
[ { "name": "Enabled", "value": { "valueKind": 6 }, "type": "bool", "defaultValue": true, "allowedValues": [] }, { "name": "Severity", "value": { "valueKind": 3 }, "type": "enum", "defaultValue": "Medium", "allowedValues": [ "Low", "Medium", "Warning", "Critical" ] } ]

Was this page helpful?
0 / 5 - 0 ratings