-
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
Support DateOnly and TimeOnly in JsonSerializer #53539
Comments
Tagging subscribers to this area: @eiriktsarpalis, @layomia Issue Details#51302 proposes adding FYI @devsko, @mattjohnsonpint, @eiriktsarpalis, @steveharter, @tarekgh, @ericstj.
|
@layomia can you move the needed part of the proposal here and we can proceed with that? |
@tarekgh 👍 . I added some notes in the description. |
I believe that supporting the |
Sounds good to me. Is this ready for API review? Should it be marked to get it on the backlog? |
We're intentionally only doing the internal converters in this iteration, so no new APIs will be added at this stage. |
I thought @layomia's API suggestion was needed to expose the converter to the source generator? Could be wrong. runtime/src/libraries/System.Text.Json/ref/System.Text.Json.cs Lines 873 to 897 in b1e20bf
|
@ericstj @eiriktsarpalis yup the source generator would need these APIs. No harm in getting this API approved and getting generator support implemented at the same time as the non-source gen code-paths. |
These APIs would be in namespace System.Text.Json.Serialization.Metadata
{
public static partial class JsonMetadataServices
{
public static JsonConverter<DateOnly> DateOnlyConverter { get; }
public static JsonConverter<TimeOnly> TimeOnlyConverter { get; }
}
} |
Surely, for netstandard 2.0 targeted library it would not be possible to even reference types that need those converters as something to create serializers for. The source generator would never reference a converter for a type not seen in the object hierarchy, as that would defeat being trimer friendly. I suppose it might be possible for a user created .netstandard2.0 library (that uses the generator for serialization and will ultimately be used in a .net6+ app) to reference another package that is multitargeted which adds some properties of these types for a .net6+ build, but generally those properties would not be serialization critical, since they totally won’t exist on older runtimes. So this normally won’t make a difference. In the rare case it does, the netstandard2.0 user library using source generators could multitarget, and would then have the extra properties in the .net6+ version(s). That is kind of fundamental though. Any shape change only seen in a multitargeted version of a referenced package will never be included in a .netstandard2.0 single-targeted library’s source generated serializers, since to do otherwise would require reflection, and avoiding that reflection is basically the whole point of the source generator. It might be nice to have some form of diagnostic warning for the library author if any such omited properties are detected, and thus won’t be included in the generated serializers. However, I’m not sure that is something that is even feasible for an analyzer, as it requires knowledge of the tfm graph, and knowing what is contained in the binaries of the other targeted tfms. In any case that would be a topic for a different issue. |
STJ builds for .NET Core, Framework, and Standard. The API shape is consistent across the TFMs. It is valid for a project targeting .NET Standard to use the generator so long as there's a reference to STJ.dll. The generator only runs if the |
I'm not sure what can be done regarding this specific issue. Related issues might arise when stale metadata is passed to the serializer to represent a given type. Actionable mitigations for right now are to include a versioning mechanism in the generated code so that the serializer can reject state implementations at runtime. This work is part of #45448. Also we'd encourage users to always (re-)run the generator when building rather than generate once and save the output. This would reduce chances of having stale/mismatched generated code. In general we do want to provide diagnostics & additional tooling if they can prevent issues, where possible, as the situations arise. |
Sounds good. I just want to make sure we don't accidentally generate code that doesn't work in .NET Standard 2.0 anymore. @KevinCathcart's comment makes sense but we need to keep in mind that people sometimes copy types and make them internal in their project. Not sure it's worth hardening the generator for this, but we know that some people do that. |
If somebody did add an internal copy of System.DateOnly to their downlevel library, what would the options even be? One (not ideal) option is that the Source Generator tries to use the built-in converter, and fails with a compile error, because it is not present. Option 2 is that the source generator sees the built-in converter does not exist, and generates it own error. Option 3 would be is that in the absence of the built-in converter it generates code treating it like any other user defined type. Options 2 or 3 are nicer than option one. Both look at a quick glance like they should not be hard to implement. Number 3 would presumably be incompatible with .net6’s serialization by default, but I think the user could register a custom converter for the type to make it compatible. Number 2 would not allow for that possibility, but avoids incompatible serialization if the user provided nothing custom. One last last possible option would be to emit a compatible version of the converter into the generated code. (Yeah, A decent extra chunk of code, and generally a bad idea, especially for an uncommon edge case. I only mention it for completeness.) There may be other reasonable options, but none spring to mind. |
I'm pretty shocked this didn't make it into 6.x and is slated for 7. This really hurts productivity and prevents people from using these new types. |
Thanks, @niemyjski. We understand the frustration that we didn't get this included in .NET 6. We do have it planned for to land in .NET 7 though, as you noted. It's expected to be included in the Preview 5-6 timeframe. |
I think we should bring this back in for API review. We are in a position to answer most of the questions raised in last year's review. There's now precedent in bifurcating ns2.0/netcoreapp APIs, cf. runtime/src/libraries/System.Formats.Cbor/ref/System.Formats.Cbor.netcoreapp.cs Lines 7 to 17 in 30a5b1f
|
I don't think we want to bifurcate, but we're OK with later versions of TFMs having more APIs than previous versions. At least to me, bifurcation would mean that ns2.0 would have APIs that the netcoreapp TFM would not have. That would be violation of versioning rules. FWIW, I think S.T.J needs to support |
@terrajobst - FYI, There's a similar issue with dotnet/maui#1100 |
namespace System.Text.Json.Serialization.Metadata;
public static partial class JsonMetadataServices
{
public static JsonConverter<DateOnly> DateOnlyConverter { get; }
public static JsonConverter<TimeOnly> TimeOnlyConverter { get; }
} |
I'm getting exceptions
I'm not passing |
@sreejith-ms You can pass |
Yes @maxkoshevoi, I can manually pass
|
The final version of this will not require passing options as the serializer will -- by default -- understand these types. |
@terrajobst The final version - you mean .NET 7 release ? |
Correct, this change will be first released in .NET 7. |
During our migration to .NET 6, I have implemented a delegating converter akin to how it's done in #69160 and I have found these edge cases:
I'm not sure this is intended. Since .NET 7 Preview 5 is not available yet, I wasn't sure if I should create a new issue for this. |
The first issue is surprising, but it seems to reproduce in both The second issue is a quirk of the current |
It is worth coding that. allowing such wrong behavior can end up supporting it forever and will be hard to fix it later. Please try to fix that. |
#51302 proposes adding
DateOnly
andTimeOnly
support to System.Text.Json: on the serializer, reader, writer, and DOM types. We won't get to all of this in 6.0 but can support them at theJsonSerializer
level now, using internal converters and building on ISO 8601 support forDateTime
andDateTimeOffset
.API Proposal
We don't need new API to support these types in the existing (non source-gen) serializer programming model. The implementation will be based on new, internal
JsonConverter<T>
s. Support will be automatic since the serializer initializes converters for all types during its warm-up phase.When the JSON source generation feature (#45448) is used, we'll need API like the following so that the generator can generate code that initializes those converters as-needed in a user's project.
Format
DateOnly
andTimeOnly
will be (de)serialized using the following formats:"yyyy'-'MM'-'dd"
"HH':'mm':'ss[FFFFFFF]"
See Date and time components for more information.
EDIT @eiriktsarpalis should be reviewed in conjunction with #29932
FYI @devsko, @mattjohnsonpint, @eiriktsarpalis, @steveharter, @tarekgh, @ericstj.
The text was updated successfully, but these errors were encountered: