2014-04-07 21 views
1

很可能我没有经历过足够的东西,我的问题有点愚蠢: 为了学习的目的,我试图连接到一个REST服务,它提供了JSON数据。带有动态根对象的JSON

从我所了解的情况来看,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; } 
    } 

但这里是我的问题:我创建了这个类的“点心”和“RootObject”通过使用本网站http://json2csharp.com/时,JSON字符串是这样看:

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

问题:名称“Khalgor”似乎被用作根对象,但它是一个名称。所以如果我想用另一个名字,我不得不使用另一个RootObject。

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

像往常一样,非常感谢所有响应

马蒂亚斯

编辑:

我修修补补角落找寻了一下,这是我的一个解决方案的第一个想法:

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:只要看看它,我就会看到很多工作要做,但我认为它背后的想法很清楚。

+0

Json的目的是为了传输目的将数据包装到字符串表示中。您提到的无状态适用于REST。 – BlueM

回答

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>(); 
     } 
    } 
} 
+0

你确定吗?我换成 public sum testProp {get;组; } 现在它总是空。看起来它确实需要“khalgor”。我可以使用类似DataMember属性的东西吗? 我真的很喜欢没有RootObject,因为我只是想要在“khalgor”属性中的数据。 –

+0

如果你解析Json到你的对象中,并且根在Json文本中没有命名为testProp,那么当然它不会被映射到你的对象。所以你的问题基本上是如何忽略根? – BlueM

+0

@MatthiasMüller查看我的更新回答。我认为这就是你想要的。它将忽略根元素的名称并提取它的一个嵌套和元素。 – BlueM

2

我认为最好的方法对JSON“碎片”是反序列化到一个动态对象:

dynamic stuff = JsonConvert.DeserializeObject(inputData); 

然后你就可以反序列化部件,使感觉入适当的.NET对象。

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

谢谢,所以没有简单的方法可以这样说:“将RootObject和Screw属性”khalgor“拧紧,然后将数据提交给我!” ? –