我正在进行 http 调用,并且响应返回(已编辑)
{
"Theaters": [
{
"id": "259cf043-6195-42dd-bfdb-640969e0bfb9",
"name": "Theater1",
"slug": "Theater1",
"shows": [
{
"id": "73436465-1f14-400f-bfbf-ab6766269e70",
"name": "show1"
},
{
"id": "9a268b42-4f13-4f7a-9c7d-d40a30d7a6eb",
"name": "show2"
}
]
},
{
"id": "9c6a0933-e519-4d6e-b027-e6c47c60641b",
"name": "Theater3",
"slug": "Theater3",
"parks": [
{
"id": "18608db3e-fa23-4284-89dd-9fcd0wes9c9c",
"name": "show3"
}
]
}
]
}
我的 C# 课程是:
public class Theater
{
public Theater()
{
shows = new List<ShowBase>();
}
public string id { get; set; }
public string name { get; set; }
public string slug { get; set; }
public ICollection<ShowBase> shows { get; set; }
}
public class ShowBase
{
public string id { get; set; }
public string name { get; set; }
}
public class TheaterList
{
public TheaterList()
{
theaters= new List<Theater>();
}
public List<Theater> theaters;
}
我正在使用通用函数来获取结果
public virtual async Task<T> Get<T>()
{
response = await client.GetAsync(URL);
Console.WriteLine(response.IsSuccessStatusCode);
string json = await response.Content.ReadAsStringAsync();
var data = JsonSerializer.Deserialize<T>(json);
return (T)Convert.ChangeType(data, typeof(T));
}
此有效负载返回空而失败 我用两种方式调用它
var result = await TheaterGetter.Get<TheaterList>();
和
var result = await TheaterGetter.Get<Theater>();
两者都空空回来,不应该。
我也尝试过这个,但收到错误消息,指出需要实施
IConvertible
。
var result = await TheaterGetter.GetList<List<Theater>, Theater>();
public virtual async Task<List<T>> GetList<T, B>()
{
response = await client.GetAsync(URL);
Console.WriteLine(response.IsSuccessStatusCode);
string json = await response.Content.ReadAsStringAsync();
var data = JsonSerializer.Deserialize<B>(json);
return (List<T>)Convert.ChangeType(data, typeof(T));
}
如有任何帮助,我们将不胜感激
您在这里遇到一些问题:
public List<Theater> theaters;
是 field 不是属性,但 System.Text.Json 默认情况下不会序列化字段。 您需要将 JsonSerializerOptions.IncludeFields
设置为 true 或将该字段更改为属性。
System.Text.Json 默认情况下区分大小写,但字段名称
theaters
与 JSON 属性名称 "Theaters"
不匹配。 您需要使它们一致或使用 JsonSerializer.Deserialize 失败 或 System.Text.Json 中 Newtonsoft.Json 的 JsonProperty 属性的等效项是什么?. 中的替代方案之一
您的根 JSON 对象对应于
TheaterList
,因此您需要在 Get<T>()
方法中使用该类型。
您将获得
string
形式的响应,然后手动反序列化该字符串。 虽然这可行,但它不会像调用 HttpClientJsonExtensions.GetFromJsonAsync()
那样高效,后者从响应流中异步反序列化,而无需中间 string
表示。
尚不清楚您是否需要这个,但您的
Theater
类型没有与 JSON 属性对应的属性 "parks"
在
Get<T>()
方法的第一个版本中,您调用
(T)Convert.ChangeType(data, typeof(T));
这不是必需的,因为
data
已经是 T
类型。
在你的第二个版本中,你调用:
(List<T>)Convert.ChangeType(data, typeof(T));
这是行不通的。 看来您正在尝试以某种通用方式返回
TheaterList.Theaters
的值,但 C# 没有内置架构来一般从一种类型转换为另一种类型,因为 Convert.ChangeType()
主要用于从 或 转换到原始类型,如 string
或 int
。
要修复#1-#5,请按如下方式修改 C# 类:
public class TheaterList
{
public List<Theater> Theaters { get; set; } = new(); // FIXED - made a property and capitalized the first letter
}
public class Theater
{
public string id { get; set; }
public string name { get; set; }
public string slug { get; set; }
public ICollection<ShowBase> shows { get; set; } = new List<ShowBase>();
public ICollection<ShowBase> parks { get; set; } = new List<ShowBase>(); // TODO: include only if required
}
public class ShowBase
{
public string id { get; set; }
public string name { get; set; }
}
你的
TheaterGetter.Get<TValue>()
方法如下:
public virtual async Task<TValue?> Get<TValue>(CancellationToken cancellationToken = default) =>
await client.GetFromJsonAsync<TValue?>(URL, cancellationToken : cancellationToken);
然后调用如下:
var result = (await TheaterGetter.Get<TheaterList>())
?.Theaters;
现在,如果您还需要修复#6——一种从
TheaterList
转换为 List<Theater>
的自动通用方法——那么没有内置任何内容,因此您需要自己完成。 一种可能性是创建一个通用接口和扩展方法,如下所示:
public interface IConvertibleTo<out TToType>
{
TToType ConvertTo();
}
public static class ConvertibleExtensions
{
public static TToType? ConvertTo<TToType>(this IConvertibleTo<TToType>? from) => from is null ? default(TToType?) : from.ConvertTo();
}
然后让
TheaterList
实现接口:
public class TheaterList : IConvertibleTo<List<Theater>>
{
List<Theater> IConvertibleTo<List<Theater>>.ConvertTo() => Theaters;
public List<Theater> Theaters { get; set; } = new();
}
最后,您将能够添加一个
TheaterGetter.Get<TDto, TValue>
方法,自动反序列化剧院列表并将其转换为剧院列表,如下所示:
public virtual async Task<TValue?> Get<TDto, TValue>(CancellationToken cancellationToken = default)
where TDto : IConvertibleTo<TValue> =>
(await Get<TDto?>(cancellationToken)).ConvertTo<TValue>();
并这样称呼它:
var result = await TheaterGetter.Get<TheaterList, List<Theater>>();
演示 #2 此处。