✅ Trouble porting to AOT JSON
I'm having some trouble making my json parsing aot-friendly. I have a lot of types to deserialize into, this is what I'm doing right now:
My issue lies with the way this is handled, there are many types nested within that have conflicting names. e.g:
The serialization context above complains about having multiple types with the name 'Nested'. This nested class is just an example; In my original code, all of the nested classes have different properties/fields
Is there an easy way to handle this? I have a lot of types, with nested type names conflicting all over the place, so renaming everything is somewhat impractical. Any advice?
32 Replies
Inheritance.
public class A: Nested {}
public class B: Nested {}
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/inheritance#background-what-is-inheritanceThis would solve the warning, yes, but it's still a ton of work to do:
I have a lot of types, with nested type names conflicting all over the placeI would have to move all nested classes outside AND give them unique names. If that was practical to begin with, I would just give them unique names while they were nested to solve the issue
Your example, they all have the same name, so if everyone inherites from
Nested
they would all have the same properties and methods derived from Nested
. If it's Nested1
and Nested2
and Nested3
and... Then I don't think there's a "quick fix" for that.Perhaps the original post wasn't clear, but while all the nested classes share the same name, they do not share the same properties/fields
Ah, if they share the same name, you can add the flag to ignore them writing
default
or null
. https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonignorecondition?view=net-8.0#fields
So, like this: [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
Why would I do this? For context the warning I'm getting is https://learn.microsoft.com/en-gb/dotnet/fundamentals/syslib-diagnostics/syslib1031
I think, without being able to see the code, it's resolving as multiple types; so it's resolving as
A
and B
or A
and C
. If you want do it based on specific properties, you can, but I've never done it - so I can't expound upon it, further.
https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-8-0#configure-polymorphism-with-the-contract-modelMy issue has nothing to do with polymorphism or inheritence, it's having different types with conflicting names. Which normally shouldn't be a problem since they are all nested. But STJ doesn't seem to recognize that:
There are multiple types named 'Nested'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.
This is the warning message. Obviously, me going through every nested type within those specified as [JsonSerializable] and giving them aliases is a lot of work (I have 50+ JsonSerializable types).
What I've wanted to know is: Can STJ do this for me? Since all the types causing trouble are nested, can STJ somehow prepend the name of the parent class to the type? Because, reading that warning, it seems like leaving things as is will break most of deserializationhow unfortunate
there is a workaround specified in these issues
are you referring to using
TypeInfoPropertyName
?looks like it to me
Ah, I've explained:
me going through every nested type within those specified as [JsonSerializable] and giving them aliases is a lot of work (I have 50+ JsonSerializable types).
yes, but there is no other way to handle this.
(currently?)
and adding a string to the attributes is really not that big a deal imo. you can even select multiple lines at once in most editors, and just do them all at the same time
when you put it like that ofc its not yeah, but what I'll have to do is something like:
you can imagine this getting tiresome very quickly lol
this is an operation of seconds for me
i select
.Nested
, press the key combination to edit all occurrences of it, use arrow keys/home/end + ctrl/shift to select the full type name and copy it, then navigate to the end of the attribute, and insert , TypeInforPropertyName = ""
and then paste the full type name
and use arrow keys + ctrl again to edit the name if i needmy reality is a little more grim I think
The warning doesn't tell you where the confliced type is. Say for example 'User' is a nested type within a lot of my JsonSerializables. The warning doesn't tell me what classes have this as nested, so I will have to go through them from the start to find one that has it
I think still your idea won't work because A.Nested != B.Nested
my idea was this
ah ok
I see the potential
but like I said I don't know what class implements what so I still cant do that
your first mistake was to nest classes ;p
I think it was one of the best choices I've made
imagine having to find a unique name for a 'user' class 20 times
why do you need more than 1 user class?
it wouldnt only suck your mind but it'll also fill your solution with files
a user in DomainA is not the same user as a user in DomainB
so you would surely have DomainASerializerContext and DomainBSerializerContext
User
carries different definitions in different contexts
but then we're back to the issue of having to create one for so many typesIf you have 1 User class with properties that get populated per domain type, those null/empties can be ignored; you can project one to many, instead of having to have 1:1. Unless you're projecting the User back to the client, the client doesn't care how you process
User
.it's hard to believe you need 50 different types of users
I am projecting the user back to a client
not 50 but X
and not just 'User', many other things too
Even then, you can do something like
GoogleUser: User
and AADUser: User
and OtherProvider: User
. Which makes User extensible and the target type derived from that. So, if you want to change DisplayName
, for example, you just have to change it in User
, once, not 50 different User
classes.what this guy said. i would never nest classes unless the nested class is private (and even then i reserve it mostly for records for internal json deserialization)
if you choose to go with nested classes which share names, then you'll unfortunately have to deal with the repercussions
you can always open another issue mentioning the other two, but it's unlikely it will get any further than those other ones