.net 为什么SortedSet不能在GitHub页面上使用Blazor webassembly反序列化?

4si2a6ki  于 2022-11-26  发布在  .NET
关注(0)|答案(1)|浏览(123)

我尝试创建一个blazor WebAssembly网站(托管在Github Pages上),它调用基于云的API(AWS),它接收一个包含SortedSet值的JSON序列化的值,并将其反序列化。
我试图隔离这个问题,最后得到了可以重现它的最少代码,也就是说,当你试图立即反序列化一个SortedSet时。

@page "/"

<button onclick="@Deserialize">Deserialize</button>
<br />Message: @message

@code
{
    private string message = "Nothing happened yet";

    private void Deserialize()
    {
        try
        {
            SortedSet<int> sortedSet = JsonSerializer.Deserialize<SortedSet<int>>("[1,2,3]");
            message = $"Deserialized SortedSet: {string.Join(",", sortedSet)}";
        }
        catch (Exception e)
        {
            message = $"Deserialization ended up in an exception: {e}";
        }
    }
}

以下是一个错误:

System.NotSupportedException: DeserializeNoConstructor, JsonConstructorAttribute,
  System.Collections.Generic.SortedSet`1[System.Int32] 
  Path: $ | LineNumber: 0 | BytePositionInLine: 1.
 ---> System.NotSupportedException: DeserializeNoConstructor,
      JsonConstructorAttribute,
      System.Collections.Generic.SortedSet`1[System.Int32]
Exception_EndOfInnerExceptionStack 
at System.Text.Json.ThrowHelper.ThrowNotSupportedException(ReadStack& , Utf8JsonReader& , NotSupportedException ) 
at System.Text.Json.ThrowHelper.ThrowNotSupportedException_DeserializeNoConstructor(Type , Utf8JsonReader& , ReadStack& ) 
at System.Text.Json.Serialization.Converters.ISetOfTConverter`2[[System.Collections.Generic.SortedSet`1[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].CreateCollection(Utf8JsonReader& , ReadStack& , JsonSerializerOptions ) 
at System.Text.Json.Serialization.JsonCollectionConverter`2[[System.Collections.Generic.SortedSet`1[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnTryRead(Utf8JsonReader& , Type , JsonSerializerOptions , ReadStack& , SortedSet`1& ) 
at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.SortedSet`1[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]].TryRead(Utf8JsonReader& , Type , JsonSerializerOptions , ReadStack& , SortedSet`1& ) 
at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.SortedSet`1[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]].ReadCore(Utf8JsonReader& , JsonSerializerOptions , ReadStack& )
at System.Text.Json.JsonSerializer.ReadFromSpan[SortedSet`1](ReadOnlySpan`1 , JsonTypeInfo , Nullable`1 )
at System.Text.Json.JsonSerializer.ReadFromSpan[SortedSet`1](ReadOnlySpan`1 , JsonTypeInfo ) 
at System.Text.Json.JsonSerializer.Deserialize[SortedSet`1](String , JsonSerializerOptions ) 
at SortedSetDeserializationDemo.Pages.Index.Deserialize()

只有在GitHub页面上托管时才会出现,并且在Visual Studio中运行时无法重现。
我已经找到了修复的方法。你应该在反序列化任何SortedSet * 之前 * 序列化任何(可能是非空的)SortedSet。
以下是一些奇怪的细节:
1.如果我在反序列化尝试之后添加序列化,仍然会出现错误
1.如果我在另一个绑定到按钮的方法中进行序列化**,即使我没有使用那个按钮**,也不会有错误。
1.反序列化列表时没有错误
可能相关的其他一些详细信息:不依赖于Release/Debug配置,我没有测试所有可能的场景,但是我测试的都产生了相同的结果,看起来可能与JIT有关,可以在Chrome和Edge中重现,使用.NET 6.0(6.0.10和6.0.11都试过)
以下是我的问题:
1.可能是什么?
1.如果是bug,是.NET/Blazor bug、GitHub页面bug还是浏览器bug?

bpzcxfmw

bpzcxfmw1#

正如@HenkHolterman在评论中提到的,在发布过程中发生了一些事情。我试图在反序列化之前比较发布输出是否具有序列化,并且似乎存在不同的System.Collections.dll。如果没有s11 n,则为8.5KB,而具有s11 n,则为13 KB。如果我仅将System.Collections.dll替换为13 KB版本,并在blazor.boot.json中调整其散列,一切都正常。我将为dotnet创建一个关于它的错误报告。

**Upd:**看来添加一个SortedSet构造函数就足够了。

它解释了我观察到的奇怪行为。它在序列化之前处理反序列化,因为我必须创建一个SortedSet来进行序列化,并且我调用了一个SortedSet构造函数。当我在反序列化之后调用Serialize(SortedSet)时,我使用了一个从反序列化中获得的值,因此没有从编译的代码中直接调用SortedSet构造函数。
在我的例子中,序列化是在反射模式下进行的,因此发布代码并不知道我的应用程序中使用了SortedSet构造函数,因此发布会修剪SortedSet无参数构造函数。
另一种变通方法是使用source generation
显然,他们不会改变任何东西,详情请参阅https://github.com/dotnet/runtime/issues/78776

相关问题