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

JSON source generator fails to compile with CS1061 if enum property decorated with [JsonConverter] #62079

Closed
martincostello opened this issue Nov 26, 2021 · 3 comments · Fixed by #62595
Assignees
Milestone

Comments

@martincostello
Copy link
Member

Description

If a object graph used with the JSON source generator has a child object with a property whose type is an enumeration which is decorated with a [JsonConverter] attribute, compilation will fail with a CS1061 error.

error CS1061: 'MyJsonContext' does not contain a definition for 'GetConverterFromFactory' and no accessible extension method 'GetConverterFromFactory' accepting a first argument of type 'MyJsonContext' could be found (are you missing a using directive or an assembly reference?)

If the [JsonConverter] attribute is removed, or if the property is not part of a child of the root node of the object graph, the code compiles.

Reproduction Steps

To reproduce run dotnet build using the .NET 6.0.100 SDK for the below application.

using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

var value = new Parent { Child = new() { Value = MyEnum.Value2 } };
var bytes = JsonSerializer.SerializeToUtf8Bytes(value, typeof(Parent), new MyJsonContext(new (JsonSerializerDefaults.Web)));
var json = Encoding.UTF8.GetString(bytes);

Console.WriteLine(json);

public enum MyEnum
{
    Value1,
    Value2,
}

public class Parent
{
    public Child? Child { get; set; }
}

public class Child
{
    // Remove the attribute below and compilation will succeed
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public MyEnum Value { get; set; }
}

[JsonSerializable(typeof(Parent))]
public partial class MyJsonContext : JsonSerializerContext
{
}
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <ImplicitUsings>enable</ImplicitUsings>
    <NoWarn>$(NoWarn);CA1050</NoWarn>
    <Nullable>enable</Nullable>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
</Project>

Expected behavior

The application compiles successfully.

Actual behavior

The application fails to compile.

> dotnet build
Microsoft (R) Build Engine version 17.0.0+c9eb9dd64 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
C:\Coding\martincostello\JsonSourceGeneratorObsoleteProperties\System.Text.Json.SourceGeneration\System.Text.Json.SourceGeneration.JsonSourceGenerator\MyJsonContext.Child.g.cs(51,41): error CS1061: 'MyJsonContext' does not contain a definition for 'GetConverterFromFactory' and no accessible extension method 'GetConverterFromFactory' accepting a first argument of type 'MyJsonContext' could be found (are you missing a using directive or an assembly reference?) [C:\Coding\martincostello\JsonSourceGeneratorObsoleteProperties\JsonSourceGeneratorObsoleteProperties.csproj]

Build FAILED.

C:\Coding\martincostello\JsonSourceGeneratorObsoleteProperties\System.Text.Json.SourceGeneration\System.Text.Json.SourceGeneration.JsonSourceGenerator\MyJsonContext.Child.g.cs(51,41): error CS1061: 'MyJsonContext' does not contain a definition for 'GetConverterFromFactory' and no accessible extension method 'GetConverterFromFactory' accepting a first argument of type 'MyJsonContext' could be found (are you missing a using directive or an assembly reference?) [C:\Coding\martincostello\JsonSourceGeneratorObsoleteProperties\JsonSourceGeneratorObsoleteProperties.csproj]
    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:01.82

Regression?

No.

Known Workarounds

No response

Configuration

Partial output from dotnet --info:

> dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.100
 Commit:    9e8b04bbff

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19043
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\6.0.100\

Host (useful for support):
  Version: 6.0.0
  Commit:  4822e3c3aa

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Text.Json untriaged New issue has not been triaged by the area owner labels Nov 26, 2021
@ghost
Copy link

ghost commented Nov 26, 2021

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

Issue Details

Description

If a object graph used with the JSON source generator has a child object with a property whose type is an enumeration which is decorated with a [JsonConverter] attribute, compilation will fail with a CS1061 error.

error CS1061: 'MyJsonContext' does not contain a definition for 'GetConverterFromFactory' and no accessible extension method 'GetConverterFromFactory' accepting a first argument of type 'MyJsonContext' could be found (are you missing a using directive or an assembly reference?)

If the [JsonConverter] attribute is removed, or if the property is not part of a child of the root node of the object graph, the code compiles.

Reproduction Steps

To reproduce run dotnet build using the .NET 6.0.100 SDK for the below application.

using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

var value = new Parent { Child = new() { Value = MyEnum.Value2 } };
var bytes = JsonSerializer.SerializeToUtf8Bytes(value, typeof(Parent), new MyJsonContext(new (JsonSerializerDefaults.Web)));
var json = Encoding.UTF8.GetString(bytes);

Console.WriteLine(json);

public enum MyEnum
{
    Value1,
    Value2,
}

public class Parent
{
    public Child? Child { get; set; }
}

public class Child
{
    // Remove the attribute below and compilation will succeed
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public MyEnum Value { get; set; }
}

[JsonSerializable(typeof(Parent))]
public partial class MyJsonContext : JsonSerializerContext
{
}
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <ImplicitUsings>enable</ImplicitUsings>
    <NoWarn>$(NoWarn);CA1050</NoWarn>
    <Nullable>enable</Nullable>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
</Project>

Expected behavior

The application compiles successfully.

Actual behavior

The application fails to compile.

> dotnet build
Microsoft (R) Build Engine version 17.0.0+c9eb9dd64 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
C:\Coding\martincostello\JsonSourceGeneratorObsoleteProperties\System.Text.Json.SourceGeneration\System.Text.Json.SourceGeneration.JsonSourceGenerator\MyJsonContext.Child.g.cs(51,41): error CS1061: 'MyJsonContext' does not contain a definition for 'GetConverterFromFactory' and no accessible extension method 'GetConverterFromFactory' accepting a first argument of type 'MyJsonContext' could be found (are you missing a using directive or an assembly reference?) [C:\Coding\martincostello\JsonSourceGeneratorObsoleteProperties\JsonSourceGeneratorObsoleteProperties.csproj]

Build FAILED.

C:\Coding\martincostello\JsonSourceGeneratorObsoleteProperties\System.Text.Json.SourceGeneration\System.Text.Json.SourceGeneration.JsonSourceGenerator\MyJsonContext.Child.g.cs(51,41): error CS1061: 'MyJsonContext' does not contain a definition for 'GetConverterFromFactory' and no accessible extension method 'GetConverterFromFactory' accepting a first argument of type 'MyJsonContext' could be found (are you missing a using directive or an assembly reference?) [C:\Coding\martincostello\JsonSourceGeneratorObsoleteProperties\JsonSourceGeneratorObsoleteProperties.csproj]
    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:01.82

Regression?

No.

Known Workarounds

No response

Configuration

Partial output from dotnet --info:

> dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.100
 Commit:    9e8b04bbff

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19043
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\6.0.100\

Host (useful for support):
  Version: 6.0.0
  Commit:  4822e3c3aa

Other information

No response

Author: martincostello
Assignees: -
Labels:

area-System.Text.Json, untriaged

Milestone: -

@eiriktsarpalis
Copy link
Member

eiriktsarpalis commented Nov 26, 2021

I can reproduce. This is related to #58267: it looks like we fixed JsonConverter declarations at the type level but missed property level declarations. cc @layomia @steveharter

@martincostello in the meantime you might be able to work around the bug by declaring the converter at the type level. If that's not possible it should still be possible to register the converter with your context like so:

var options = new JsonSerializerOptions { Converters = { new JsonStringEnumConverter() } };
var context = new MyJsonContext(options);
JsonSerializer.Serialize(new Child(), context.Child);

@eiriktsarpalis eiriktsarpalis added this to the 6.0.x milestone Nov 26, 2021
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Nov 26, 2021
@martincostello
Copy link
Member Author

Thanks @eiriktsarpalis - we use those in our app already so we should be good will the attribute commented out for me trying out the source generator. We just also used the attribute to ensure that other apps consuming the models via our NuGet packages would get the right behaviour out-of-the-box without having to specifically set up the JsonSerializerOptions.

@eiriktsarpalis eiriktsarpalis self-assigned this Nov 30, 2021
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Dec 9, 2021
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Dec 10, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Jan 9, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
2 participants