System.Text.Json JsonSerializer:不支持 'System.Type' 个实例的序列化和反序列化
System.Text.Json JsonSerializer: Serialization and deserialization of 'System.Type' instances are not supported
当我尝试使用 `System.Text.Json JsonSerializer` 反序列化时,我遇到了与安全相关的错误。
我想达到什么目的?
我想让用户控制转换我数据库中的一些记录,所以使用可以遵循这个场景:
1- 用户可以选择我的 class 库的模型。
2- 在 selecting a class 之后,用户将从这个 class.
select a 属性(filed)
3- 用户将获得 selected 属性 的值列表。
4- 最后一步现在不在这里,用户可以编辑一个 certian 值。
这是我的一段代码:
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});
}
public async ValueTask<List<T>> 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>();
由于安全原因,System.Text.Json 不支持类型 class。您将完整的程序集名称作为字符串发送,然后再次尝试在客户端构造类型。
就像@Mayur Ekbote 提到的那样,“System.Text.Json 出于安全原因不支持 class 类型。”我会添加一个解决方案,但我认为这个解决方案不是很有效。
将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
而不是选定的列表 class.
当我尝试使用 `System.Text.Json JsonSerializer` 反序列化时,我遇到了与安全相关的错误。
我想达到什么目的?
我想让用户控制转换我数据库中的一些记录,所以使用可以遵循这个场景:1- 用户可以选择我的 class 库的模型。
2- 在 selecting a class 之后,用户将从这个 class.
select a 属性(filed) 3- 用户将获得 selected 属性 的值列表。
4- 最后一步现在不在这里,用户可以编辑一个 certian 值。
这是我的一段代码:
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}); }
public async ValueTask<List<T>> 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>();
System.Text.Json 不支持类型 class。您将完整的程序集名称作为字符串发送,然后再次尝试在客户端构造类型。
就像@Mayur Ekbote 提到的那样,“System.Text.Json 出于安全原因不支持 class 类型。”我会添加一个解决方案,但我认为这个解决方案不是很有效。
将
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
而不是选定的列表 class.