C
C#3w ago
occluder

✅ 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:
[JsonSerializable(typeof(A))]
[JsonSerializable(typeof(B))]
[JsonSerializable(typeof(C))]
public partial class ExampleSerializationContext : JsonSerializerContext
{
}
[JsonSerializable(typeof(A))]
[JsonSerializable(typeof(B))]
[JsonSerializable(typeof(C))]
public partial class ExampleSerializationContext : JsonSerializerContext
{
}
My issue lies with the way this is handled, there are many types nested within that have conflicting names. e.g:
public class A
{
public class Nested
{ }
}

public class B
{
public class Nested
{ }
}

public class C
{
public class Nested
{ }
}
public class A
{
public class Nested
{ }
}

public class B
{
public class Nested
{ }
}

public class C
{
public class Nested
{ }
}
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
occluder
occluderOP3w ago
This 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 place
I 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
felsokning
felsokning3w ago
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.
occluder
occluderOP3w ago
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
felsokning
felsokning3w ago
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)]
occluder
occluderOP3w ago
Why would I do this? For context the warning I'm getting is https://learn.microsoft.com/en-gb/dotnet/fundamentals/syslib-diagnostics/syslib1031
felsokning
felsokning3w ago
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-model
occluder
occluderOP3w ago
My 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 deserialization
occluder
occluderOP3w ago
how unfortunate
ero
ero3w ago
there is a workaround specified in these issues
occluder
occluderOP3w ago
are you referring to using TypeInfoPropertyName ?
ero
ero3w ago
looks like it to me
occluder
occluderOP3w ago
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).
ero
ero3w ago
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
occluder
occluderOP3w ago
when you put it like that ofc its not yeah, but what I'll have to do is something like:
[JsonSerializable(typeof(A))]
[JsonSerializable(typeof(A.Nested),TypeInfoPropertyName = "NestedA")]
[JsonSerializable(typeof(B))]
[JsonSerializable(typeof(B.Nested),TypeInfoPropertyName = "NestedB")]
...
public partial class ExampleSerializationContext : JsonSerializerContext
{
}
[JsonSerializable(typeof(A))]
[JsonSerializable(typeof(A.Nested),TypeInfoPropertyName = "NestedA")]
[JsonSerializable(typeof(B))]
[JsonSerializable(typeof(B.Nested),TypeInfoPropertyName = "NestedB")]
...
public partial class ExampleSerializationContext : JsonSerializerContext
{
}
you can imagine this getting tiresome very quickly lol
ero
ero3w ago
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 need
occluder
occluderOP3w ago
my 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
ero
ero3w ago
my idea was this
occluder
occluderOP3w ago
ah ok I see the potential but like I said I don't know what class implements what so I still cant do that
ero
ero3w ago
your first mistake was to nest classes ;p
occluder
occluderOP3w ago
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
ero
ero3w ago
why do you need more than 1 user class?
occluder
occluderOP3w ago
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
ero
ero3w ago
so you would surely have DomainASerializerContext and DomainBSerializerContext
occluder
occluderOP3w ago
User carries different definitions in different contexts but then we're back to the issue of having to create one for so many types
felsokning
felsokning3w ago
If 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.
ero
ero3w ago
it's hard to believe you need 50 different types of users
occluder
occluderOP3w ago
I am projecting the user back to a client not 50 but X and not just 'User', many other things too
felsokning
felsokning3w ago
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.
ero
ero3w ago
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
Want results from more Discord servers?
Add your server