Skip to content

Commit

Permalink
Fixes `System.InvalidOperationException: This JsonSerializerOptions i…
Browse files Browse the repository at this point in the history
…nstance is read-only or has already been used in serialization or deserialization` (#480)

* Updated NuGet packages

* Attempt to fix publish

* Removed static JSON serializer options instance
  • Loading branch information
xperiandri committed Jun 16, 2024
1 parent e8fedf6 commit 16aa6e0
Show file tree
Hide file tree
Showing 15 changed files with 27 additions and 32 deletions.
8 changes: 7 additions & 1 deletion samples/star-wars-api/Startup.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,20 @@ type Startup private () =

let rootFactory (ctx) : Root = Root (ctx)

/// Added for testing purposes because in .NET 8 JsonSerializerOptions become frozen after the first use
/// and using this function caused an exception.
let configure (options : GraphQLOptions<_>) =
options.SerializerOptions.Converters.Add (new System.Text.Json.Serialization.JsonStringEnumConverter ())
options

new (configuration : IConfiguration) as this =
Startup ()
then this.Configuration <- configuration

member _.ConfigureServices (services : IServiceCollection) =
services
.AddGiraffe()
.AddGraphQLOptions<Root> (Schema.executor, rootFactory)
.AddGraphQLOptions<Root> (Schema.executor, rootFactory, configure = configure)
|> ignore

member _.Configure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,3 @@ let getWSSerializerOptions (additionalConverters: JsonConverter seq) =
options |> configureDefaultWSSerializerOptions additionalConverters
options

let serializerOptions = getWSSerializerOptions Seq.empty
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module ServiceCollectionExtensions =
SchemaExecutor = executor
RootFactory = rootFactory
ReadBufferSize = GraphQLOptionsDefaults.ReadBufferSize
SerializerOptions = Json.serializerOptions
SerializerOptions = Json.getWSSerializerOptions Seq.empty
WebsocketOptions = {
EndpointUrl = endpointUrl
ConnectionInitTimeout = TimeSpan.FromMilliseconds (GraphQLOptionsDefaults.WebSocketConnectionInitTimeoutInMs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ open FSharp.Data.GraphQL.Server.AspNetCore
open FSharp.Data.GraphQL.Server.AspNetCore.WebSockets

let toClientMessage (theInput : string) =
let serializerOptions = Json.serializerOptions
JsonSerializer.Deserialize<ClientMessage> (theInput, serializerOptions)

let willResultInInvalidMessage expectedExplanation input =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ open FSharp.Data.GraphQL.Server.AspNetCore
open FSharp.Data.GraphQL.Server.AspNetCore.WebSockets
open System.Text.Json.Serialization

let serializerOptions = Json.serializerOptions

[<Fact>]
let ``Deserializes ConnectionInit correctly`` () =

Expand Down
3 changes: 1 addition & 2 deletions tests/FSharp.Data.GraphQL.Tests/ExecutionTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Parser
open FSharp.Data.GraphQL.Execution
open FSharp.Data.GraphQL.Server.AspNetCore

type TestSubject = {
a: string
Expand Down Expand Up @@ -131,7 +130,7 @@ let ``Execution handles basic tasks: executes arbitrary code`` () =

let schema = Schema(DataType)
let schemaProcessor = Executor(schema)
let params' = JsonDocument.Parse("""{"size":100}""").RootElement.Deserialize<ImmutableDictionary<string, JsonElement>>(Json.serializerOptions)
let params' = JsonDocument.Parse("""{"size":100}""").RootElement.Deserialize<ImmutableDictionary<string, JsonElement>>(serializerOptions)
let result = sync <| schemaProcessor.AsyncExecute(ast, data, variables = params', operationName = "Example")
ensureDirect result <| fun data errors ->
empty errors
Expand Down
6 changes: 4 additions & 2 deletions tests/FSharp.Data.GraphQL.Tests/Helpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ open System.Threading
open System.Threading.Tasks
open Xunit
open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Server.AspNetCore

let serializerOptions = Json.getWSSerializerOptions Seq.empty

let isType<'a> actual = Assert.IsAssignableFrom<'a>(actual)
let isSeq<'a> actual = isType<'a seq> actual
Expand Down Expand Up @@ -74,11 +77,10 @@ let greaterThanOrEqual expected actual =

open System.Text.Json
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Server.AspNetCore

let stringifyArg name (ctx : ResolveFieldContext) () =
let arg = ctx.TryArg name |> Option.toObj
JsonSerializer.Serialize (arg, Json.serializerOptions)
JsonSerializer.Serialize (arg, serializerOptions)

let stringifyInput = stringifyArg "input"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ open FSharp.Data.GraphQL.Ast
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Parser
open FSharp.Data.GraphQL.Execution
open FSharp.Data.GraphQL.Server.AspNetCore
open ErrorHelpers

let TestComplexScalar =
Expand Down Expand Up @@ -113,7 +112,7 @@ let variablesWithInput inputName input = $"""{{"%s{inputName}":%s{input}}}"""
let paramsWithValueInput input =
JsonDocument
.Parse(variablesWithInput "input" input)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (Json.serializerOptions)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)

let testInputObject =
"""{"mand":"baz","opt1":"foo","opt2":null,"optSeq":["bar"],"voptSeq":["bar"],"optArr":null,"voptArr":null}"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Parser
open FSharp.Data.GraphQL.Execution
open FSharp.Data.GraphQL.Server.AspNetCore

let stringifyArg name (ctx : ResolveFieldContext) () =
let arg = ctx.TryArg name |> Option.toObj
JsonSerializer.Serialize (arg, Json.serializerOptions)
JsonSerializer.Serialize (arg, serializerOptions)

let stringifyInput = stringifyArg "input"

Expand All @@ -45,7 +44,7 @@ let variablesWithInput inputName input = $"""{{"%s{inputName}":%s{input}}}"""
let paramsWithEnumInput input =
JsonDocument
.Parse(variablesWithInput "enumVar" input)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (Json.serializerOptions)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)

[<Fact>]
let ``Execute handles enum input as variable`` () =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Parser
open FSharp.Data.GraphQL.Execution
open FSharp.Data.GraphQL.Server.AspNetCore
open ErrorHelpers

let stringifyArg name (ctx : ResolveFieldContext) () =
let arg = ctx.TryArg name |> Option.toObj
JsonSerializer.Serialize (arg, Json.serializerOptions)
JsonSerializer.Serialize (arg, serializerOptions)

let stringifyInput = stringifyArg "input"

Expand All @@ -41,7 +40,7 @@ let variablesWithInput inputName input = $"""{{"%s{inputName}":%s{input}}}"""
let paramsWithValueInput input =
JsonDocument
.Parse(variablesWithInput "input" input)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (Json.serializerOptions)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)

[<Fact>]
let ``Execute handles list inputs and nullability and allows lists to be null`` () =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Parser
open FSharp.Data.GraphQL.Execution
open FSharp.Data.GraphQL.Server.AspNetCore

let InputArrayOf (innerDef : #TypeDef<'Val>) : ListOfDef<'Val, 'Val array> = ListOf innerDef

Expand Down Expand Up @@ -60,7 +59,7 @@ let rec TestRecursiveInputObject =

let stringifyArg name (ctx : ResolveFieldContext) () =
let arg = ctx.TryArg name |> Option.toObj
JsonSerializer.Serialize (arg, Json.serializerOptions)
JsonSerializer.Serialize (arg, serializerOptions)

let stringifyInput = stringifyArg "input"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Parser
open FSharp.Data.GraphQL.Execution
open FSharp.Data.GraphQL.Server.AspNetCore
open ErrorHelpers

let stringifyArg name (ctx : ResolveFieldContext) () =
let arg = ctx.TryArg name |> Option.toObj
JsonSerializer.Serialize (arg, Json.serializerOptions)
JsonSerializer.Serialize (arg, serializerOptions)

let stringifyInput = stringifyArg "input"

Expand All @@ -46,7 +45,7 @@ let variablesWithInput inputName input = $"""{{"%s{inputName}":%s{input}}}"""
let paramsWithValueInput input =
JsonDocument
.Parse(variablesWithInput "input" input)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (Json.serializerOptions)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)

[<Fact>]
let ``Execute handles variables and allows nullable inputs to be omitted`` () =
Expand Down Expand Up @@ -99,7 +98,7 @@ let ``Execute handles variables and allows nullable inputs to be set to a value
let paramsWithValueInput input =
JsonDocument
.Parse(variablesWithInput "value" input)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (Json.serializerOptions)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)

let testInputValue = "\"a\""
let params' = paramsWithValueInput testInputValue
Expand Down Expand Up @@ -130,7 +129,7 @@ let ``Execute handles non-nullable scalars and does not allow non-nullable input
let paramsWithValueInput input =
JsonDocument
.Parse(variablesWithInput "value" input)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (Json.serializerOptions)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)

let testInputValue = "null"
let params' = paramsWithValueInput testInputValue
Expand All @@ -149,7 +148,7 @@ let ``Execute handles non-nullable scalars and allows non-nullable inputs to be
let paramsWithValueInput input =
JsonDocument
.Parse(variablesWithInput "value" input)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (Json.serializerOptions)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)

let testInputValue = "\"a\""
let params' = paramsWithValueInput testInputValue
Expand Down Expand Up @@ -181,7 +180,7 @@ let ``Execute uses argument default value when no argument was provided`` () =
let paramsWithOptionalInput input =
JsonDocument
.Parse(variablesWithInput "optional" input)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (Json.serializerOptions)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)

[<Fact>]
let ``Execute uses argument default value when nullable variable provided`` () =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ open FSharp.Data.GraphQL.Parser
open FSharp.Data.GraphQL.Execution
open FSharp.Data.GraphQL.Validation
open FSharp.Data.GraphQL.Validation.ValidationResult
open FSharp.Data.GraphQL.Server.AspNetCore
open ErrorHelpers

type InputRecord = { Country : string; ZipCode : string; City : string }
Expand Down Expand Up @@ -158,7 +157,7 @@ let variablesWithAllInputs (record, record1, record2, record3) =
let paramsWithValues variables =
JsonDocument
.Parse(variables : string)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (Json.serializerOptions)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)

[<Fact>]
let ``Execute handles validation of valid input records from variables with all fields`` () =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ open System.Text.Json
open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Parser
open FSharp.Data.GraphQL.Server.AspNetCore

type InputRecord = { a : string; b : string; c : string }

Expand Down Expand Up @@ -143,7 +142,7 @@ let variablesWithAllInputs (record, optRecord) =
let paramsWithValues variables =
JsonDocument
.Parse(variables : string)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (Json.serializerOptions)
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)

[<Fact>]
let ``Execute handles creation of input records from variables with all fields`` () =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ open System.Text.Json
open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Parser
open FSharp.Data.GraphQL.Server.AspNetCore

module Phantom =

Expand Down

0 comments on commit 16aa6e0

Please sign in to comment.