给定这个JSON,
{
"token": {
"accessToken": "scrciFyGuLAQn6XgKkaBWOxdZA1",
"issuedAt": "2022-11-06T22:54:27Z",
"expiresIn": 1799
}
}
我可以让DeserializeObject
工作,如果我定义模型为这个
public class Root
{
public Token Token { get; set; }
}
public class Token
{
public string AccessToken { get; set; }
public DateTime IssuedAt { get; set; }
public int ExpiresIn { get; set; }
}
并使用这个调用:
Root myRoot = JsonConvert.DeserializeObject<Root>(apiResponse);
我调用的第三方API具有返回类似JSON响应的所有方法,因为它具有包含特定类型的单个对象的头对象,例如:
{
"user": {
"preferences": {},
"address": {},
"name": {},
"email": "string",
"segmentName": "string"
}
}
需要一个像这样的模型:
public class Address
{
}
public class Name
{
}
public class Preferences
{
}
public class Root
{
public User user { get; set; }
}
public class User
{
public Preferences preferences { get; set; }
public Address address { get; set; }
public Name name { get; set; }
public string email { get; set; }
public string segmentName { get; set; }
}
我不想为每个JSON响应定义不同的Root
类。有办法避免这种情况吗?
编辑14/11。
另一个JSON响应如下:
{
"provider": {
"TOTAL": {
"count": 0
}
}
}
还是一个"空"根对象,包含我需要的特定对象。
zaitsman 在他的评论中指出,通过输入DeserializeObject
调用来使用<Dictionary, T>
,其中T
是我所追求的实际对象(例如Token
或User
或Provider
),它绕过了对根对象的需要。
编辑15/11。
再举一个例子;
{
"provider": [
{
"accountType": [],
"loginHelp": "string",
"baseUrl": "string",
"loginUrl": "string",
"name": "string",
"id": 0,
"lastModified": "string",
"status": "Supported"
}
]
}
在这种情况下,要反序列化的 c# 代码看起来像这样:
providers = JsonConvert.DeserializeObject<Dictionary<string, List<Provider>>>(apiResponse)["provider"];
使用Dictionary<string,T>
消除了定义根类的需要,并且T
必须定义为List<T>
,因为内容是一个数组。
有很多方法可以达到这个目的。
其中之一是:
JsonConvert.DeserializeObject<Dictionary<string, User>>()["user"]
这将给你一个Dictionary<string, User>
,所以你可以使用任何其他合适的类型。
我认为定义Root
对象是更好的方法,因为它使预期的JSON结构明确定义,但如果你想,你可以使用Newtonsoft的LINQ API通过JObject
(docs):
var jObject = JObject.Parse(json);
var user = jObject["user"].ToObject<User>();
类似的可以通过JsonNode API为System.Text.Json
(可从。net 6开始)完成。
解决这个问题的一种方法是使用包装器定义所有可能的"内容";名称作为属性。然后有一个属性返回反序列化后填充的值。
public class Response<T>
{
public User User { get; set; }
public Token Token { get; set; }
public Token AuthToken { get; set; }
public XYZ XYZ { get; set; }
public T Content => GetType().GetProperties().Where(p => p.Name != nameof(Content)).Select(p => p.GetValue(this)).Single(v => v != null) as T;
}
那么,只要有一个像这样的反序列化方法
public T DeserializeResponse<T>(string json)
{
return Deserialize<Response<T>>(json).Content;
}
还有一种更动态的方法,如果你需要检索太多不同的内容,但这将需要覆盖一些更多的反射,并深入到反序列化过程。