Skip to content
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

fix(JsonPicker, JsonIsomorphism, UnionConverter)!: Reduce greediness #113

Merged
merged 4 commits into from
Jan 27, 2024

Conversation

bartelink
Copy link
Collaborator

@bartelink bartelink commented Jan 24, 2024

Removes two speculative 'features' that can be reaonably argued to be misfeatures on the basis that they were not documented, nor were they covered by tests:

  1. JsonPickler no longer supports implicit application (via inclusion in the converters list) to parent types or interfaces
    • (also affects JsonIsomorphism, which inherits from it)
  2. SystemTextJson.Options: autoTypeSafeEnumToJsonString, union = autoUnionToJsonObject are skipped if the type nominates a specific converter directly (used to also honor tags on base classes/interfaces)

In both cases, the workaround if this greediness was intentionally required, is to override the CanConvert member on the converter (or UnionOrTypeSafeEnumConverterFactory)

@bartelink bartelink changed the title refactor: Small cleanups chore: Formatting, SDK 8 Jan 24, 2024
[<AbstractClass>]
type JsonPickler<'T>() =
inherit Serialization.JsonConverter<'T>()

static let isMatchingType =
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eiriktsarpalis Apologies for yet more atting but I don't think I can answer it without you...

  1. what desirable behaviors am I likely to be removing/breaking with this?
  2. can you point me to anything that implements similar behavior, perhaps with some tests/docs/use cases?

My thinking is that I should have removed it long ago, as it does not fail the tests, and I can't think of a use case...

i.e. am I missing anything regarding some polymorphic behavior that's going over my head?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming you only use it to deserialize values (which is a naturally covariant operation) and never to serialize then it should work expected.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm can you expand on that please? i.e. can you paint me a scenario as to how you do that, composing something with multiple pickers or something? i.e. what sort of a global hook would it afford one?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming you have Foo <: IFoo and you define a converter JsonConverter<Foo> whose CanConvert method returns true when given typeof<IFoo>, then the serializer will use that as the converter for IFoo. The downside however is that it will fail with a cast exception if you ever attempt to serialize values of type IFoo (since they may not be castable to Foo).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! The main thing is that there's a pretty clear extension point for people to override the default behavior
(and it matches the general expectations one would have from STJ in terms of not being greedy by default)

Thankfully I've the luxury of not thinking too deeply about polymorphism wrt serialization in my day to day work ;)

Also now (V3 RC) is the right time to take out the behavior, if it's ever going to be done...

@bartelink bartelink changed the base branch from master to net8 January 27, 2024 00:09
@bartelink bartelink changed the title chore: Formatting, SDK 8 fix(JsonPicker, JsonIsomorphism)!: Reduce greediness Jan 27, 2024
@bartelink bartelink force-pushed the cleanups branch 3 times, most recently from 097c9ec to e4d99a2 Compare January 27, 2024 00:53
@bartelink bartelink changed the title fix(JsonPicker, JsonIsomorphism)!: Reduce greediness fix(JsonPicker, JsonIsomorphism, UnionConverter)!: Reduce greediness Jan 27, 2024
abstract Read: reader: byref<Utf8JsonReader> * options: JsonSerializerOptions -> 'T

override _.CanConvert t = isMatchingType t
Copy link
Collaborator Author

@bartelink bartelink Jan 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note base class has an (=) t semantic (which also matches the impl the NSJ version implements directly)

@@ -5,12 +5,13 @@ open System.Text.Json.Serialization
type UnionOrTypeSafeEnumConverterFactory(typeSafeEnum, union) =
inherit JsonConverterFactory()

static let hasConverterAttribute: System.Type -> bool = memoize _.IsDefined(typeof<JsonConverterAttribute>, true)
static let cache = System.Collections.Concurrent.ConcurrentDictionary<System.Type, bool>()
static let typeHasConverterAttribute t: bool = cache.GetOrAdd(t, fun (t: System.Type) -> t.IsDefined(typeof<JsonConverterAttribute>, ``inherit`` = false))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note flipping behavior to be less greedy (not honoring attributes on base types), to match Newtonsoft impl

Base automatically changed from net8 to master January 27, 2024 01:09
@bartelink bartelink merged commit 8d2f198 into master Jan 27, 2024
9 checks passed
@bartelink bartelink deleted the cleanups branch January 27, 2024 01:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants