简体   繁体   中英

System.Text.Json JsonSerializer: Serialization and deserialization of 'System.Type' instances are not supported


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

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.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM