带动态Root-Object的JSON

时间:2014-04-07 20:53:09

标签: c# rest

可能我没有经验,我的问题有点愚蠢: 出于学习目的,我尝试连接到提供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; }
    }

但这是我的问题:我已经创建了这个课程&#34; Sum&#34;和&#34; RootObject&#34;通过使用网站http://json2csharp.com/,JSON-String看起来像这样:

{"khalgor":{"id":23801741,"name":"Khalgor","profileIconId":7,"summonerLevel":30,"revisionDate":1396876104000}}

问题:名字&#34; Khalgor&#34;似乎是用作Root-Object,但它是一个Name。因此,如果我想要用户使用其他名称,我必须使用另一个RootObject。

创建这样的结构没有多大意义,所以我的问题是:这里的最佳做法是什么?我是否手动将此RootObject / Property映射到另一个对象?我是否使用一些反射动态创建属性或重命名它?

像往常一样,非常感谢所有回复

的Matthias

编辑:

我纠结了一点,这是我对解决方案的第一个想法:

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。我确定它不适用于所有事情,但我想这会是一个好方法吗?

Edit2:只要看一下,我就会看到我有很多工作要做,但我认为背后的想法很清楚。

2 个答案:

答案 0 :(得分:2)

我认为你最好的赌注是json&#34;片段&#34;是反序列化为动态对象:

dynamic stuff = JsonConvert.DeserializeObject(inputData);

然后,您可以将对正确的.NET对象有意义的部分反序列化。

SomeObject o = JsonConvert.DeserializeObject<SomeObject>(stuff["someProperty"].ToString());

答案 1 :(得分:1)

如果要完全忽略根(例如,每次更改其名称),请使用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>();
        }
    }
}