对JSON还不太熟悉,并且遇到了一个对我来说不明显的问题。
我正在查询的api返回一个标准的响应对象,其中处理的命令/ api请求的结果嵌入在json中的数据对象中。
因此,对于API上的所有请求,响应如下所示,数据组件的变化取决于所请求的内容。
ObjectType1响应
{
"data": {
"person" : {
"id" : 21,
"name" : "Json can be annoying at times"
}
},
"message" : "",
"result" : "success"
}
或api上的其他请求将返回以下
列表ObjectType2响应
{
"data": {
"1234" : {
"id": 1234,
"title" : "Terminator"
},
"3245" : {
"id" : 3245,
"name" : "Terminator 2"
}
},
"message" : "",
"result" : "success"
}
我想有一个自定义JsonConverter将响应拉出到对象中
public class MyResponse {
[JsonProperty(PropertyName = "data")]
public string Data { get; set; }
[JsonProperty(PropertyName = "message")]
public string Message { get; set; }
[JsonProperty(PropertyName = "status")]
public string Status { get; set; }
}
或
public class MyResponse<T> : class T {
public T Data { get; set; }
public string Message { get; set; }
public string Status { get; set; }
}
然后从那里我可以在泛型方法中对Status / message执行操作,然后将json字符串返回给我库中的调用方法。从中可以根据请求正确处理返回的json字符串。
任何想法如何将数据的子对象反序列化为字符串,甚至更好,如果我将方法传递给泛型类型T我怎样才能将json反序列化为两个对象。
修改
为那些希望做类似事情的人发表以下答案
干杯
答案 0 :(得分:1)
感谢那些提供帮助的人,但我最终想出了我想要的答案,将我的对象反序列化为通过泛型提供的正确类型。
这是我的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();
}
}
为了使用上面的内容,我创建了一个类似于以下内容的Generic方法,允许我传递命令来运行,额外的查询字符串以及Type以将'Data'对象转换为:
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结构的人,如果有人看到更简单的方法来实现转换器,我很乐意接受任何输入。
干杯
答案 1 :(得分:0)
对于JSON对象的序列化/反序列化,请查看Json.NET。您可以将其包含为Nuget包,并使用内置方法,例如JsonConvert.SerializeObject(Object object)
和JsonConvert.DeserializeObject(string value, Type type)
。
您可以通过使用JsonProperty
属性修饰模型来控制JSON属性的名称。例如:
public class MyResponse {
[JsonProperty(PropertyName = "data")]
public string Data { get; set; }
[JsonProperty(PropertyName = "message")]
public string Message { get; set; }
[JsonProperty(PropertyName = "status")]
public string Status { get; set; }
}
答案 2 :(得分:0)
两个实体:
public class Response
{
public Dictionary<string, Data> data { get; set; }
public string message { get; set; }
public string result { get; set; }
}
public class Data
{
public int id { get; set; }
public string title { get; set; }
}
回复代码是:
JavaScriptSerializer serializer = new JavaScriptSerializer();
Response response = (Response) serializer.Deserialize<Response>(jsonString);
如您所见,没有其他套餐