2013-09-26 65 views
2

例如,我有一些类:反序列化字典<string, T>

class User 
    { 
     int Id {get; set;} 
     string Name {get; set;} 
    } 

    class Venue 
    { 
     int Id {get; set;} 
     string Adress {get; set;} 
    } 

    class Message 
    { 
    string Text {get; set;} 
    int FromId {get; set;} 
    } 

我把JSON从网页:

[%user% => {id: 1, name: "Alex"}, %user% => {id: 5, name: "John"}] 

我可以分析它:

var myObjects = JsonConvert.DeserializeObject<Dictionary<string, User>>(json); 

但如果有一个json:

[%user% => {id: 1, name: "Alex"}, %venue% => {id: 465, adress: "Thomas at 68th Street"}, %message% => {text: "hello", fromId: 78}] 

我可以定义键%用户%=用户,场地%(%)=地点等类型..

但我怎么能分析它?

在此先感谢!

UPDATE

我目前的解决方案:

private JsonSerializerSettings _jsonSettings = new JsonSerializerSettings 
     { 
      TypeNameHandling = TypeNameHandling.All, 
      TypeNameAssemblyFormat = FormatterAssemblyStyle.Full 
     }; 

string myJson = "{\"%user%\":{\"id\" : 5, \"name\" : \"John\"}, \"%venue%\":{\"id\" : \"5f56de\", \"adress\": \"Thomas at 68th Street\"}}"; 

Dictionary<string, object> dict = 
       JsonConvert.DeserializeObject<Dictionary<string, object>> 
       (myJson, _jsonSettings); 

Dictionary<string, object> d = new Dictionary<string, object>(); 

foreach(var o in dict) 
{ 
       string json = (string)o.Value.ToString(); 

       switch (o.Key) 
       { 
        case "%user%": 
         { 
          var v = JsonConvert.DeserializeObject<User>(json); 
          d.Add(o.Key, v); 
          break; 
         } 

        case "%venue%": 
         { 
          var v = JsonConvert.DeserializeObject<Venue>(json); 
          d.Add(o.Key, v); 
          break; 
         } 
        case "%message%": 
         { 
          var v = JsonConvert.DeserializeObject<Message>(json); 
          d.Add(o.Key, v); 
          break; 
         } 
       } 
    } 
+0

你的问题和更新实际上给了我一个线索来解决我用Json解析的问题。谢谢! – varagrawal

回答

2

如果您正在使用Json.Net(又名Newtonsoft.Json),您可以创建自定义JsonConverter对象。这个对象允许定制json的解析。因此,考虑以下类

public class User 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public class Venue 
{ 
    public string Id { get; set; } 
    public string Address { get; set; } 
} 

public class Message 
{ 
    public string Text { get; set; } 
    [JsonProperty("fromId")] 
    public string FromId { get; set; } 
} 

你可以限制那些被分配了一个JsonConverter

[JsonConverter(typeof(PostJsonConverter))] 
public class Post 
{ 
    public User User { get; set; } 
    public Venue Venue { get; set; } 
    public Message Message { get; set; } 
} 

的JsonConvter类是有三个方法的抽象类,你需要覆盖其他类中。你会想实现ReadJson方法。如果您不需要编写json,那么无需在WriteJson方法中执行任何操作。

public class PostJsonConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     // not implemented 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     // it must be an object being passed in, if not something went wrong! 
     if (reader.TokenType != JsonToken.StartObject) throw new InvalidOperationException(); 

     var postToken = JToken.ReadFrom(reader); 
     var userToken = postToken["%user%"]; 
     var venueToken = postToken["%venue%"]; 
     var messageToken = postToken["%message%"]; 

     return new Post 
     { 
      User = userToken == null ? null : userToken.ToObject<User>(), 
      Venue = venueToken == null ? null : venueToken.ToObject<Venue>(), 
      Message = messageToken == null ? null : messageToken.ToObject<Message>(), 
     }; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return true; 
    } 
} 

没有额外的工作需要,因为我们已经给班上JsonConverterAttribute这种正常的转换转换。

string myJson = "{\"%user%\":{\"id\" : 5, \"name\" : \"John\"}, \"%venue%\":{\"id\" : \"5f56de\", \"address\": \"Thomas at 68th Street\"}}"; 
Post post = JsonConvert.DeserializeObject<Post>(myJson); 
0

这里是一个简洁的可能的解决方案,用我的小JSON解析器库:

  public class User 
      { 
        public int Id { get; set; } 
        public string Name { get; set; } 
      } 

      public class Venue 
      { 
        public int Id { get; set; } 
        public string Address { get; set; } 
      } 

      public class Message 
      { 
        public string Text { get; set; } 
        public int FromId { get; set; } 
      } 

      /* Deals with this SO question : 
      * 
      * http://stackoverflow.com/questions/19023696/deserialize-dictionarystring-t 
      */ 
      public static void SO_19023696() 
      { 
        Console.Clear(); 
        Console.WriteLine("StackOverflow question 19023696 - Polymorphic, key-driven Test"); 
        Console.WriteLine(); 
        string myJson = @" 
     [ 
      { 
       ""%user%"" : { ""id"": 1, ""name"": ""Alex""} , 
       ""%venue%"" : { ""id"": 465, ""address"": ""Thomas at 68th Street"" }, 
       ""%message%"" : { ""text"": ""hello"", ""fromId"": 78 } 
      }, 
      { 
       ""%user%"" : { ""id"": 2, ""name"": ""Carl""} , 
       ""%message%"" : { ""text"": ""bye"", ""fromId"": 79 } 
      } 
     ]"; 

        Dictionary<string, object>[] parsed = 
          JSON.Map(null as Dictionary<string, object>[]). 
            FromJson 
            (
              myJson, 
              JSON.Map(default(Dictionary<string, object>)). 
                Using // Deal with the main issue raised by the SO question: 
                (
                  (outer, type, value) => 
                    ((outer.Hash != null) && outer.Hash.ContainsKey("Name") ? (Func<object>) 
                    (() => new User { Id = (int)outer.Hash["Id"], Name = (string)outer.Hash["Name"] }) : 
                      ((outer.Hash != null) && outer.Hash.ContainsKey("Address") ? (Func<object>) 
                      (() => new Venue { Id = (int)outer.Hash["Id"], Address = (string)outer.Hash["Address"] }) : 
                        ((outer.Hash != null) && outer.Hash.ContainsKey("Text") ? (Func<object>) 
                        (() => new Message { FromId = (int)outer.Hash["FromId"], Text = (string)outer.Hash["Text"] }) : 
                          null 
                        ) 
                      ) 
                    ) 
                ), 
              Sample_Revivers.CamelCaseToPascalCase, 
              Sample_Revivers.DoubleToInteger 
            ); 
        System.Diagnostics.Debug.Assert(parsed[0]["%user%"] is User); 
        System.Diagnostics.Debug.Assert(parsed[0]["%venue%"] is Venue); 
        System.Diagnostics.Debug.Assert(parsed[0]["%message%"] is Message); 
        System.Diagnostics.Debug.Assert(parsed[1]["%user%"] is User); 
        System.Diagnostics.Debug.Assert(parsed[1]["%message%"] is Message); 
        Console.Write("Passed - Press a key..."); 
        Console.ReadKey(); 
      } 

更多的用例/例子,通过通用的字典,或匿名类型,或波苏斯,可以在这里找到:

https://code.google.com/p/ysharp/source/browse/trunk/TestJSONParser/BasicTests.cs

相关问题