具有动态根对象的 JSON
本文关键字:JSON 对象 动态 | 更新日期: 2023-09-27 17:57:08
可能是我没有足够的经验,我的问题有点愚蠢:出于学习目的,我正在尝试连接到提供JSON数据的REST服务。
根据我所学到的知识,JSON 的目的是将相同的数据交付给任何可能的客户端,而无需自身状态。
我的代码看起来像这样:
public static void DoSomething()
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("SomeUrl"));
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// List data response.
HttpResponseMessage response = client.GetAsync("").Result;
if (response.IsSuccessStatusCode)
{
Task<Stream> readTask = response.Content.ReadAsStreamAsync();
readTask.ContinueWith(task =>
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(RootObject));
using (Stream result = task.Result)
{
result.Position = 0;
RootObject obj = (RootObject)ser.ReadObject(result);
}
});
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
}
public class Sum
{
public int id { get; set; }
public string name { get; set; }
public int profileIconId { get; set; }
public int summonerLevel { get; set; }
public long revisionDate { get; set; }
}
public class RootObject
{
public Sum khalgor { get; set; }
}
但这是我的问题:我使用网站创建了这个类"Sum"和"RootObject"http://json2csharp.com/,JSON-String 看起来像这样:
{"khalgor":{"id":23801741,"name":"Khalgor","profileIconId":7,"summonerLevel":30,"revisionDate":1396876104000}}
问题:"Khalgor"这个名字似乎被用作根对象,但它是一个名字。因此,如果我想使用另一个名称,我必须使用另一个根对象。
创建这样的结构没有多大意义,所以我的问题:这里的最佳实践是什么?我是否手动将此根对象/属性映射到另一个对象?我是否使用某些反射来动态创建属性或重命名它?
像往常一样,非常感谢所有回复
马蒂亚斯
编辑:
我捣鼓了一下,这是我对解决方案的第一个想法:
public static class LOLObjectFactory
{
public static ILOLObject Create(string jsonString)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
Dictionary<String, object> entry = (jss.Deserialize<dynamic>(jsonString) as Dictionary<string, object>).First().Value as Dictionary<String, object>;
Type selectedType = null;
List<string> fieldNames = entry.Select(f => f.Key).OrderBy(f => f).ToList();
Type[] types = typeof(ILOLObject).Assembly.GetTypes();
foreach(var type in types)
{
List<string> typeProperties = type.GetProperties().Select(f => f.Name).OrderBy(f => f).ToList();
if (fieldNames.SequenceEqual(typeProperties) && typeof(ILOLObject).IsAssignableFrom(type))
{
selectedType = type;
break;
}
}
ILOLObject result = System.Activator.CreateInstance(selectedType) as ILOLObject;
foreach(var prop in result.GetType().GetProperties())
{
prop.SetValue(result, entry.First(f => f.Key == prop.Name).Value);
}
return result;
}
}
因此,我拥有的所有对象都实现了ILOLObject。我确定它不适用于所有内容,但我想这将是一个很好的方法?
编辑2:只要看一看,我就知道我还有很多工作要做,但我认为它背后的想法非常清楚。
我认为 json"片段"的最佳选择是反序列化为动态对象:
dynamic stuff = JsonConvert.DeserializeObject(inputData);
然后,可以将有意义的部分反序列化为适当的 .NET 对象。
SomeObject o = JsonConvert.DeserializeObject<SomeObject>(stuff["someProperty"].ToString());
如果你想完全忽略根(例如,它每次都会改变它的名字),使用 Json.NET 将其解析为一个对象并忽略最顶层的元素。例:
JObject obj = JObject.Parse(json);
if (obj != null)
{
var root = obj.First;
if (root != null)
{
var sumJson = root.First;
if (sumJson != null)
{
var sum = sumJson.ToObject<Sum>();
}
}
}