runtime: System.Text.Json can't deserialize type with more than 64 ctor parameters.

Description

Overview

Deserialize<TValue>(String, JsonSerializerOptions) can not deserialize a type with more than 64 ctor-parameters.

Observations:

  • Serialization of such type works fine (however deserialization fails).
  • This (64-ctor-param-max) limit is not documented anywhere – at least I couldn’t find it.
  • C# class doesn’t have a 64-ctor-max-param limit.

Source Of Problem:

runtime/src/libraries/System.Text.Json/Common/JsonConstants.cs

// The maximum number of parameters a constructor can have where it can be supported by the serializer.
public const int MaxParameterCount = 64;

I wonder how this (64-max) was chosen, and if it could be removed or at least made configurable. NOTE: MaxDepth is configurable.

Reproduction Steps

Create Sample Class:

  • Create an immutable class (with only get properties).
  • Add at least 65 member properties to this class.
  • Add a constructor that takes at least 65 arguments (one for each property)
  • Instantiate this class, and serialize it to a string.

Recreate The Error:

  • Attempt to deserialize this string back to the object using: JsonSerializer.Deserialize<TType>(jsonString, jsonOptions);
  • It will throw an exception similar to the following:

Sample Error:

The deserialization constructor on type '{}' may not have more than 64 parameters for deserialization.
Path: $[0] | LineNumber: 0 | BytePositionInLine: {}. ---> System.NotSupportedException:
The deserialization constructor on type '{}' may not have more than 64 parameters for deserialization.

Expected behavior

I expect to not have this limit. For classes without custom serialization (e.g. converters), System.Text.Json should be able to deserialize/serialize the output of what it serialized/deserialized.

How Found:

  • I serialized a data-class (which has more than 64 ctor parameters) to string.
  • Then I attempted to deserialize the class back to object.
  • If failed.

Actual behavior

See sample exception above.

Regression?

Don’t know; public const int MaxParameterCount = 64; was added a long time ago…

Known Workarounds

If you want immutable classes, then I don’t know. You might be able to use init in the property (e.g. public string MachineName { get; init; }). However, I’m not sure if it’s affected by issue #58770 An alternative that might work could be to use [JsonInclude].

Configuration

No response

Other information

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 3
  • Comments: 25 (14 by maintainers)

Commits related to this issue

Most upvoted comments

FYI, if we change this behavior we should update following exception message:

  <data name="ConstructorMaxOf64Parameters" xml:space="preserve">
    <value>The deserialization constructor on type '{0}' may not have more than 64 parameters for deserialization.</value>
  </data>

We hear your pain, and we’ll try to have this fixed in an upcoming release. In the meantime, please consider upvoting the OP so that it features more prominently in our backlog.

I made this suggestion earlier to make it configurable and I am wondering what you think about it?

I don’t think this should be made configurable, there should not be a limit in the first place. But for this to happen, we need to investigate scalability of the existing implementation and improve it if doesn’t scale.

@GrabYourPitchforks do you recall a discussion around an upper limit? I believe the algorithm is O(n2) so it may be related to that.