【问题标题】:Why SortedSet cannot be deserialized using Blazor webassembly on GitHub Pages?为什么不能使用 GitHub Pages 上的 Blazor webassembly 反序列化 SortedSet?
【发布时间】:2022-11-25 02:20:26
【问题描述】:

我试图制作一个调用基于云的 API (AWS) 的 blazor WebAssembly 网站(托管在 Github Pages 上)。它接收一个包含 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 Pages 上时出现,从 Visual Studio 运行时我无法重现它。

我已经找到了如何修复它。您应该序列化任何(可能是非空的)SortedSet反序列化任何 SortedSet。

这里有一些奇怪的细节:

  1. 正确添加序列化还是报错反序列化尝试
  2. 序列化没有报错在另一种方法中,绑定到一个按钮。即使我不使用那个按钮.
  3. 反序列化列表时没有错误

    其他一些可能相关的细节: 它不依赖于发布/调试配置。我没有测试所有可能的场景,但我测试的场景产生了相同的结果。看来可能和JIT有关。 它可以在 Chrome 和 Edge 中重现。 使用 .NET 6.0(尝试了 6.0.10 和 6.0.11)

    这是我的问题:

    1. 它可能是什么?
    2. 如果是错误,它是 .NET/Blazor 错误、GitHub Pages 错误还是浏览器错误?

【问题讨论】:

  • 当你做一个完整的发布时,一个额外的构建工具被用来删除它发布的所有代码认为未使用。您的症状清楚地表明这是问题所在。
  • 您已经有了解决方法:在某处添加一个小方法,主动使用所涉及的(反)序列化代码。它必须在某处调用,否则也可能被删除。您可以从 Program.cs 调用一个小虚拟对象。
  • 它看起来确实像一个错误,您可以在 GitHub 上发布问题。
  • @HenkHolterman,谢谢!你似乎是正确的。在这两个变体(带序列化和不带序列化)中有不同的 System.Collections.dll。我只替换了 System.Collections.dll 及其在 blazor.boot.json 中的散列,现在它可以工作了!
  • 好的,很高兴它有效。但是 relacing DLL 看起来像 hack,将在下一次发布时被覆盖。我暂时会使用解决方法。

标签: c# .net blazor github-pages blazor-webassembly


【解决方案1】:

正如@HenkHolterman 在 cmets 中提到的那样,发布期间会发生一些事情。我试图在反序列化之前比较有序列化和没有序列化的发布输出,看起来有不同的 System.Collections.dll。没有 s11n 是 8.5KB,有 s11n 是 13KB。如果我仅将 System.Collections.dll 替换为 13KB 版本并在 blazor.boot.json 中调整其哈希,则一切正常。我将为 dotnet 创建一个关于它的错误报告。

更新:似乎添加一个 SortedSet 构造函数就足够了。

它解释了我观察到的奇怪行为。它在序列化之前与反序列化一起工作,因为我必须创建一个 SortedSet 来序列化,并且我调用了一个 SortedSet 构造函数。当我在反序列化后调用 Serialize(SortedSet) 时,我使用了从反序列化中获得的值,因此没有直接从编译代码调用 SortedSet 构造函数。

在我的例子中,序列化发生在反射模式中,因此发布代码不知道我的应用程序中使用了 SortedSet 构造函数。因此发布修剪 SortedSet 无参数构造函数。

另一个解决方法是使用source generation

显然,他们不会对此进行任何更改,有关详细信息,请参阅https://github.com/dotnet/runtime/issues/78776

【讨论】:

    猜你喜欢
    • 2021-08-30
    • 1970-01-01
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多