【问题标题】:System.Text.Json JsonSerializer: Serialization and deserialization of 'System.Type' instances are not supportedSystem.Text.Json JsonSerializer:不支持“System.Type”实例的序列化和反序列化
【发布时间】:2021-10-05 07:55:07
【问题描述】:

当我尝试使用 `System.Text.Json JsonSerializer` 进行反序列化时,出现与安全性相关的错误。
  • 我想实现什么?
    我想让用户控制我的数据库中的一些记录,所以使用可以遵循这个场景:

    1- 用户可以选择我的类库的模型。
    2- 选择一个类后,用户将从该类中选择一个属性(归档)。
    3-用户将获得所选属性的值列表。
    4- 最后一步现在不在这里,用户可以编辑一个特定的值。

这是我的一段代码:

  • MyPage.razor.cs:

    [Inject]
    private  IGenericHttpClient<Type> HttpClient { get; set; }
    private Type SelectedType { get; set; }
    
    // First select a class [Class library] from HTML Select
    private void OnTypeChnage(ChangeEventArgs args)
    {
       string FullName = "My.Models." + args.Value.ToString();
       // Create type of selected class
       SelectedType = Assemble.GetType(FullName, false);
    }
    //Call api to get all fields of this class
    private async Task OnPropertChange(ChangeEventArgs args)
    {
       var list = await 
      HttpClient.GetJsonAsync($"/api/{SelectedType.Name}/all");
    }
    
  • GenericHttpClient.cs

    public async ValueTask<List<T>> GetJsonAsync(string url)
      {
          using HttpResponseMessage response = await _client.GetAsync(url);
          ValidateResponse(response);
          var conetnt =  await response.Content.ReadAsStringAsync();
          //I got the error down
          return JsonSerializer.Deserialize<List<T>>(conetnt, new JsonSerializerOptions() { PropertyNameCaseInsensitive=true});
      }
    

【问题讨论】:

    标签: c# asp.net-core blazor system.text.json


    【解决方案1】:

    出于安全原因,System.Text.Json 不支持 Type 类。您将完整的程序集名称作为字符串发送,然后再次尝试在客户端构造类型。

    【讨论】:

    • 嗨@Mayur,我知道Type class 会导致问题,请您帮我实现您所说的“您将完整的程序集名称作为字符串发送,然后再次尝试构造类型在客户端。”
    • 您能否详细说明您的用例/流程?
    • 好的,我会添加一些解决方案,但效率不是很高,所以请阅读它,如果你能做得更好,那就太好了!。
    • 我认为我们遇到了 XY 问题。使用动态,尤其是在 HTTP 请求等中,并不是很有用。您不妨使用字典。如果您能说明您的职能/业务目标,这将有助于我们更快地找到解决方案。
    【解决方案2】:

    public async ValueTask&lt;List&lt;T&gt;&gt; GetJsonAsync(string url) 这甚至不会编译,因为没有指定方法签名的通用信息。

    而且,您的问题可能来自 http 响应的内容,否则,Deserialize 步骤应该可以正常工作。

    我复制了你的代码并制作了一个小块来证明它。

    // Define somewhere
    public class GenericHttpClient
    {
        public List<T> GetJsonAsync<T>()
        {
            var content = "[{\"TestProp\": \"This is some test\"}]";
            return JsonSerializer.Deserialize<List<T>>(content, new JsonSerializerOptions() { PropertyNameCaseInsensitive=true});
        }
    }
    
    public class Test
    {
        public string TestProp { get; set; }
    }
    
    // Test it
    var test = new GenericHttpClient();
    var result = test.GetJsonAsync<Test>();
    

    【讨论】:

    • 谢谢 Gordon,你说得对,但我这里没有特定的类,选择的类来自 HTML 选择,我的意思是用户必须选择类,然后我必须获取数据
    【解决方案3】:

    就像@Mayur Ekbote 提到的那样,“由于安全原因,System.Text.Json 不支持 Type 类。”我会添加一个解决方案,但我认为这个解决方案效率不高。

    • Type 更改为Dynamic

        [Inject]
        private  IGenericHttpClient<dynamic> HttpClient { get; set; }
      
    • 使用JsonElement 获取字符串形式的值:

            private async Task OnPropertChange(ChangeEventArgs args)
            {
             var langCode = CultureInfo.CurrentCulture.Name;
             PropertyValueList.Clear();
      
            var list = await HttpClient.GetJsonAsync($"/api/{SelectedType.Name}/all");
            List<object> listValue = new List<object>();
      
            SelectedProperty = args.Value.ToString();
            string fieldName = char.ToLower(SelectedProperty[0]) + SelectedProperty.Substring(1);
            foreach (var item in list)
            {
                //Convert object to JsonElement
                var val = ((JsonElement)item).GetProperty(fieldName).GetString();
                PropertyValueList.Add(val);
      
            }
      
        }
      
    • 为什么没有效率?
      因为我得到了一个值列表 String 而不是所选类的列表。

    【讨论】:

      猜你喜欢
      • 2021-06-29
      • 2021-12-30
      • 2021-07-17
      • 2021-12-08
      • 1970-01-01
      • 2016-10-21
      • 2018-08-21
      • 2019-10-07
      • 2014-01-23
      相关资源
      最近更新 更多