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

[API Proposal]: Add generic versions of System.Text.Json.Serialization attributes #72936

Open
jhartmann123 opened this issue Jul 27, 2022 · 10 comments
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Text.Json
Milestone

Comments

@jhartmann123
Copy link

jhartmann123 commented Jul 27, 2022

Background and motivation

With the introduction of generic attributes, some attributes in System.Text.Json.Serialization are good candidates for generic versions, as all public constructors require a type parameter, namely:

API Proposal

namespace System.Text.Json

public class JsonConverterAttribute<T> : JsonConverterAttribute
{
    public JsonConverterAttribute() : base(typeof(T))
    { }
}

public class JsonDerivedTypeAttribute<T> : JsonDerivedTypeAttribute
{
    public JsonDerivedTypeAttribute() : base(typeof(T))
    { }

    public JsonDerivedTypeAttribute(string typeDiscriminator) : base(typeof(T), typeDiscriminator)
    { }

    public JsonDerivedTypeAttribute(int typeDiscriminator) : base(typeof(T), typeDiscriminator)
    { }
}

API Usage

[JsonDerivedType<Derived>()]
public class Base
{
    public int X { get; set; }
}

public class Derived : Base
{
    public int Y { get; set; }
}

Alternative Designs

No response

Risks

No response

@jhartmann123 jhartmann123 added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Jul 27, 2022
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Jul 27, 2022
@ghost
Copy link

ghost commented Jul 27, 2022

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis
See info in area-owners.md if you want to be subscribed.

Issue Details

Background and motivation

With the introduction of generic attributes, some attributes System.Text.Json.Serialization are good candidates for generic generic versions, as all public constructors require a type parameter, namely:

API Proposal

namespace System.Text.Json

public class JsonConverterAttribute<T> : JsonConverterAttribute
{
    public JsonConverterAttribute() : base(typeof(T))
    { }
}

public class JsonDerivedTypeAttribute<T> : JsonDerivedTypeAttribute
{
    public JsonDerivedTypeAttribute() : base(typeof(T))
    { }

    public JsonDerivedTypeAttribute(string typeDiscriminator) : base(typeof(T), typeDiscriminator)
    { }

    public JsonDerivedTypeAttribute(int typeDiscriminator) : base(typeof(T), typeDiscriminator)
    { }
}

API Usage

[JsonDerivedType<Derived>()]
public class Base
{
    public int X { get; set; }
}

public class Derived : Base
{
    public int Y { get; set; }
}

Alternative Designs

No response

Risks

No response

Author: jhartmann123
Assignees: -
Labels:

api-suggestion, area-System.Text.Json

Milestone: -

@PaulusParssinen
Copy link
Contributor

I tried this for JsonSerializableAttribute here: #71712

@eiriktsarpalis
Copy link
Member

Closing as duplicate of #71712. See #71712 (comment) for a justification.

@eiriktsarpalis eiriktsarpalis closed this as not planned Won't fix, can't repro, duplicate, stale Jul 27, 2022
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Jul 27, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Aug 26, 2022
@eiriktsarpalis
Copy link
Member

Reopening for consideration in the future.

@dotnet dotnet unlocked this conversation Sep 26, 2022
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Sep 26, 2022
@eiriktsarpalis eiriktsarpalis added this to the Future milestone Sep 26, 2022
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Sep 26, 2022
@IEvangelist
Copy link
Member

Thanks for reconsidering this @eiriktsarpalis!

@eiriktsarpalis
Copy link
Member

Possible API shape:

namespace System.Text.Json

public class JsonConverterAttribute<TConverter> : JsonConverterAttribute
    where TConverter : JsonConverter
{
    public JsonConverterAttribute();
}

public class JsonDerivedTypeAttribute<TDerivedType> : JsonDerivedTypeAttribute
     where TDerivedType : class
{
    public JsonDerivedTypeAttribute();
    public JsonDerivedTypeAttribute(string typeDiscriminator);
    public JsonDerivedTypeAttribute(int typeDiscriminator);
}

public class JsonSerializableAttribute<T> : JsonSerialiableAttribute
{
    public class JsonSerializableAttribute();
}

@aradalvand
Copy link

aradalvand commented Oct 6, 2023

It's strange this didn't make it to .NET 8 at least, given how trivial it would be to add.

It's the sort of thing you'd intuitively expect to be there at this point, since C# has supported generic attributes for a while now; it's always ugly to have [SomeAttribute(typeof(SomeType)] usages in general.

@eiriktsarpalis
Copy link
Member

It's the sort of thing you'd intuitively expect to be there at this point, since C# has supported generic attributes for a while now; it's always ugly to have [SomeAttribute(typeof(SomeType)] usages in general.

From a cost-benefit perspective adding generic variants of existing attributes introduces duplication while not offering a whole lot of benefit. Other than saving the need to type five characters, they mostly don't enhance type safety and they cannot be used in .NET languages that don't support generic attributes. We've kept this open for future consideration, although it doesn't register very high in our priorities for the time being.

@aradalvand
Copy link

aradalvand commented Oct 6, 2023

introduces duplication while not offering a whole lot of benefit.

This reasoning makes no sense; the "duplication" (if we can call it that) that it introduces is minimal and the benefit is just better syntax and ehanced type-safety.

they mostly don't enhance type safety

They do though, you can pass any type to the constructor of JsonConverterAttribute (e.g. [JsonConverter(typeof(int))]) while the generic version would enforce that it's a JsonConverter.

@eiriktsarpalis
Copy link
Member

they mostly don't enhance type safety

They do though, you can pass any type to the constructor of JsonConverterAttribute (e.g. [JsonConverter(typeof(int))]) while the generic version would enforce that it's a JsonConverter.

It wouldn't do anything when it comes to enforcing the right converter type though, so I might be annotating a property of type int with a JsonConverter<string> and the generic attribute would be none the wiser. It's true that it would be rejecting [JsonConverter<int>] annotations, but that's just guarding against pathological inputs -- I don't see how it could enhance type safety in real terms.

FWIW it's fairly straightforward to define generic attributes in your code, if you need them:

public class MyPoco
{
    [JsonConverter<JsonStringEnumConverter>]
    public BindingFlags Value { get; set; }
}

public class JsonConverterAttribute<T>() : JsonConverterAttribute(typeof(T))
    where T : JsonConverter
{ }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Text.Json
Projects
None yet
Development

No branches or pull requests

5 participants