What would be the best way of making STJ deserialize correctly for cases where the type of the constructor parameter does not match the type of the property with a matching name?
Consider the following code sample:
using System.Text.Json;
string data = """
{
"Ints": [24, 43, 54, 23]
}
""";
var parsed = JsonSerializer.Deserialize<Data>(data)!;
class Data
{
public Data(IEnumerable<int> ints)
{
Ints = ints.ToList().AsReadOnly();
}
public IReadOnlyCollection<int> Ints { get; }
}
The type of the constructor parameter ints
does not match the type of the property Ints
. This makes deserialization fail although this use case looks very reasonable.
Deserialization works as expected with Newtonsoft but I’d like to use STJ if possible.
The exception message:
System.InvalidOperationException:
Each parameter in the deserialization constructor on type 'Data' must bind to an object property or field on deserialization.
Each parameter name must match with a property or field on the object.
Fields are only considered when 'JsonSerializerOptions.IncludeFields' is enabled.
The match can be case-insensitive.
2
Answers
Check out the How to use immutable types and non-public accessors with System.Text.Json docs. One way to handle is to introduce
JsonConstructor
:Or using property with private setter and parameterless ctor:
Other than that you can look into creating a custom converter.
why just don’t use this
but if you really want to deserialize json as a ReadOnlyCollection, you need to add a field to keep this data as ReadOnlyCollection