-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JsonConverter doesn't allow injection of parameters #42975
Comments
@fbrum, can you share a small complete repro (e.g. a project, sanitized if necessary) that highlights the issue? Given this line where you add your converter to the global converters list, it is not clear to me why your specified options are not being honored. SerializerSettings.Converters.Add(new ToNullableDateTimeOffset(clientOptions.DateTimeFormat!, timeSpan));
How is this |
Hi @layomia , Just realized something! The problem is that on the contract I will have something like this example: public class Buyer
{
[JsonPropertyName("buyerBirthDate")]
[JsonConverter(typeof(NullableToDateTimeFormat))]
public DateTimeOffset? DateOfBirth { get; set; }
[JsonPropertyName("buyingDateTime")]
[JsonConverter(typeof(NullableToDateTimeFormat))]
public DateTimeOffset? BuyingDateTime { get; set; }
} Now, if I don't specify the Given that we will have the following: #399 So, I thought that if the converter was already created and added to the Converters list, it would use that one and not instantiate a new one. So I believe the suggestion here is to: |
Thanks, this issue has been fixed in 5.0 - #528
Choosing a converter from the Does the solution of adding a public parameterless constructor to the converter work for you? If I understand your scenario correctly, I think this would mean that the properties that the converter is placed would be serialized without custom formatting or a custom offset. Is this the desired behavior?
Given the above |
Correct. It does work but without the custom formatting. For now the solution is to leave it hard coded.
Yes. The current scenario we have both cases.
I understand, but my suggestion is to use the converter from attribute and when instantiating, instead of calling a default empty constructor, it could first see if there is an instance of the type in the attribute on the converters list. |
How would you describe the logical reasoning for doing this? Why is the converter attribute on the property if it should lose out to a converter on the Perhaps one reason for using a global converter over a converter on a property is to support overriding the (de)serialization behavior for a property on non-owned type. This is something we haven't received much feedback about. FWIW - another tool available if you need to pass state to a parameterized ctor of a converter on a property is to pass the type of a public class Buyer
{
[JsonPropertyName("buyerBirthDate")]
[JsonConverter(typeof(NullableDateTimeConverterFactory))]
public DateTimeOffset? DateOfBirth { get; set; }
}
public class NullableDateTimeConverterFactory : JsonConverterFactory
{
public override bool CanConvert(typeToConvert) => typeToConvert == typeof(DateTimeOffset?);
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
new ToNullableDateTimeOffset(...);
} |
I see your point about the hierarchy. But still the possibility of dependency injection for a attribute converter presides. It is an interesting case but maybe not so important. I didn't look into it, but maybe the converter per type could look into the property name or attribute to decide the conversion. So yes, the reasoning for an attribute converter to do a look up on the Converters list is to enable Dependency injection. |
A common approach I use is to define a derived class that hardcodes constructor parameters, for example public class CamelCaseStringEnumConverter : JsonStringEnumConverter
{
public CamelCaseStringEnumConverter() : base(namingPolicy: JsonNamingPolicy.CamelCase)
{
}
}
public class MyPoco
{
[JsonConverter(typeof(JsonStringEnumConverter))]
public Enum PropA { get; }
[JsonConverter(typeof(CamelCaseStringEnumConverter))] // change parameters for specific property
public Enum PropB { get; }
public enum Enum { A, B, C }
} If your DI needs are scoped to property definitions, then this approach should suffice. If instead you're scoping it per serialization, it might make sense to take a look at the proposals discussed in #34773. |
This issue has been automatically marked Please refer to our contribution guidelines for tips on what information might be required. |
This issue will now be closed since it had been marked |
I wanted to create a converter for DateTimeOffset and having the date format being injected from configuration.
But I came to conclude that is not possible. I created a base converter
And then I defined a specific converter:
Added the serializer with the converter to the collection:
I had to create a empty constructor because otherwise I would have a NullException while serializing.
And the constructor with the injected properties are not used. on the serialization.
I searched arround but was not able to find anything solution.
Could this be done for a future version?
Thanks
PS. Sorry but I'm not able to get the code formated correctly
The text was updated successfully, but these errors were encountered: