感谢那些提供帮助的人,但我最终想出了我正在寻找的答案,它将我的对象反序列化为通过泛型提供的适当类型。
这是我的 MyCustomResponse 对象
public class MyCustomResponse
{
[JsonProperty(PropertyName = "data")]
public object Data { get; set; }
[JsonProperty(PropertyName = "message")]
public string Message { get; set; }
[JsonProperty(PropertyName = "result")]
public string Result { get; set; }
}
自定义的 JsonConverter 就这样结束了,我在 json 字符串“data”中查找属性,然后将其转换为 T 类型的对象
public class MyCustomResponseConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(MyCustomResponse));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object instance = objectType.GetConstructor(Type.EmptyTypes).Invoke(null);
PropertyInfo[] props = objectType.GetProperties();
JObject jo = JObject.Load(reader);
foreach ( JProperty jp in jo.Properties() )
{
PropertyInfo prop = props.FirstOrDefault(pi =>
pi.CanWrite && string.Equals(pi.Name, jp.Name, StringComparison.OrdinalIgnoreCase));
if ( prop != null )
{
// Convert data object to what was passed in at T
if ( jp.Name == "data" )
prop.SetValue(instance, jo.SelectToken("data").ToObject(typeof(T)));
else
prop.SetValue(instance, jp.Value.ToObject(prop.PropertyType, serializer));
}
}
return instance;
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
为了使用上述方法,我创建了一个如下所示的通用方法,并允许我传递要运行的命令、额外的查询字符串以及将“数据”对象转换为的类型:
private async Task<T> GenericApiRequestAsync<T>(string command, string query)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Uri uri = new Uri(string.Format("{0}/api/{1}/?cmd={2}{3}", apiUrl, apiKey, command, query));
try {
HttpResponseMessage response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
// Convert responseContent via MyCustomResponseConverter
var myCustomResponse =
await Task.Factory.StartNew(() =>
JsonConvert.DeserializeObject<MyCustomResponse(
responseContent,
new MyCustomResponseConverter<T>()
));
return (T)myCustomResponse.Data;
}
catch(Exception ex)
{
...
}
}
然后要使用实际的 GenericApiRequestAsync 方法,我只需将要转换的 Data 对象的命令、查询和类型传递给它,无论它可能是什么。
public async Task<Person> GetPersonAsync(int id)
{
return await GenericApiRequestAsync<Person>("person.byid", string.Format("&id={0}", id));
}
public async Task<IDictionary<string, ObjectType2>> GetObjectType2ListAsync(string name)
{
return await GenericApiRequestAsync<IDictionary<string, ObjectType2>>("show.byname", string.Format("&name={0}", name));
}
最终得到了一个简单的解决方案,但实现起来却很复杂。它也消除了在最终对象中再次处理数据对象的需要。
希望此解决方案可以帮助遇到类似 JSON 结构的其他人,如果有人看到实现转换器的更简单方法,我很乐意接受任何输入。
干杯