Home > Blockchain >  System.Text.Json JsonSerializer: Serialization and deserialization of 'System.Type' instan
System.Text.Json JsonSerializer: Serialization and deserialization of 'System.Type' instan

Time:10-05


I got an error related with security when I tried to deserialize by using `System.Text.Json JsonSerializer`.
  • What do I want to achieve?
    I want to give the user controle to transalte some records in my database, so use can follow this scenario:

    1- User can choose model of my class library.
    2- After selecting a class, user will select a property(filed) from this class.
    3- User will get list of values of the selected property up.
    4- Last step is not here right now, user can edit a certian value.

This my piece of code:

  • 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});
      }
    

CodePudding user response:

System.Text.Json does not support Type class due to security reasons. You send the full assembly name as a string and again try to construct the Type at the client end.

CodePudding user response:

public async ValueTask<List<T>> GetJsonAsync(string url) this wont even compile, due to not specify generic information on method signature.

And also, your problem would come from the content of http response, otherwise, the Deserialize step should work fine.

I copied your code and make a small block that prove it.

// 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>();

CodePudding user response:

Like what @Mayur Ekbote mentioned up, "System.Text.Json does not support Type class due to security reasons." I will add a solution but I don't think this solution is very efficient.

  • Change Type to Dynamic:

      [Inject]
      private  IGenericHttpClient<dynamic> HttpClient { get; set; }
    
  • Use JsonElement to get the value as a string:

          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);
    
          }
    
      }
    
  • Whay is not efficient?
    Because I got a list of value String instead of list of selected class.

  • Related