2012-07-19 39 views
14

Tôi đang cố gắng chuyển đổi một số công việc cũ hơn để sử dụng Newtonsoft JSON.NET. Xử lý mặc định bằng cách sử dụng phương thức System.Web.Script.Serialization.JavaScriptSerializer.Deserialize (ví dụ: nếu không có loại mục tiêu nào được chỉ định) là trả lại Dictionary<string,object> cho các đối tượng bên trong.Deserialize JSON đệ quy đến IDictionary <string, object>

Đây thực sự là một loại cơ bản thực sự hữu ích cho JSON vì nó cũng là loại cơ bản được sử dụng bởi ExpandoObjects và là triển khai nội bộ hợp lý nhất cho các loại động.

Nếu tôi chỉ định loại này, ví dụ .:

var dict = JsonConvert.DeserializeObject<Dictionary<string,object>>(json); 

JSON.NET sẽ deserialize cấu trúc đối tượng ngoài cùng một cách chính xác, nhưng nó sẽ trả về một loại JObject cho bất kỳ cấu trúc nội tại. Những gì tôi thực sự cần là cho cùng một cấu trúc bên ngoài được sử dụng cho bất kỳ cấu trúc kiểu đối tượng bên trong nào.

Có cách nào để chỉ định loại được sử dụng cho các đối tượng bên trong không chỉ loại trả về ngoài cùng?

Trả lời

7

Khi Deserializing đối tượng phức tạp của bạn bằng cách sử dụng Json, bạn cần thêm một cài đặt JsonSerializer làm tham số. Điều này sẽ đảm bảo rằng tất cả các kiểu bên trong được deserialized đúng cách.

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

Khi Serializing đối tượng của bạn, bạn có thể sử dụng SerializerSettings:

string json= JsonConvert.SerializeObject(myObject, _jsonSettings) 

Sau đó, khi bạn đang deserializing, sử dụng:

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

Ngoài ra, khi bạn serialize, thêm JsonSerializerSettings để SerializeObject của bạn (đối tượng, cài đặt)

Chỉnh sửa: Bạn cũng có thể thay đổi t ông TypeNameHandling và TypeNameAssemblyFormat nếu bạn cần. Tôi đặt chúng ở vị trí 'Tất cả' và 'Đầy đủ' để đảm bảo rằng các đối tượng phức tạp của tôi được sắp xếp theo thứ tự và được deserialized đúng mà không nghi ngờ gì, nhưng intellisense cung cấp cho bạn các lựa chọn thay thế khác

+0

Đây có phải là câu trả lời đúng không? –

+1

@LukePuplett Tôi không nghĩ điều này là đúng, dựa trên câu hỏi được hỏi. –

+0

Dựa trên câu hỏi, đây không phải là câu trả lời đúng. –

15

Để có được Json.Net để deserialize một chuỗi json vào một IDictionary<string, object> bao gồm deserializing các đối tượng lồng nhau và mảng, bạn sẽ cần phải tạo một lớp tùy chỉnh có nguồn gốc từ lớp trừu tượng JsonConverter được cung cấp bởi Json.Net.

Đó là trong nguồn gốc của bạn JsonConverter nơi bạn đặt việc thực hiện cách đối tượng nên được ghi vào và từ json.

Bạn có thể sử dụng tùy chỉnh của bạn JsonConverter như thế này:

var o = JsonConvert.DeserializeObject<IDictionary<string, object>>(json, new DictionaryConverter()); 

Dưới đây là một phong tục JsonConverter Tôi đã sử dụng thành công trong quá khứ để đạt được những mục tiêu giống như bạn phác thảo trong câu hỏi của bạn:

public class DictionaryConverter : JsonConverter { 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { this.WriteValue(writer, value); } 

    private void WriteValue(JsonWriter writer, object value) { 
     var t = JToken.FromObject(value); 
     switch (t.Type) { 
      case JTokenType.Object: 
       this.WriteObject(writer, value); 
       break; 
      case JTokenType.Array: 
       this.WriteArray(writer, value); 
       break; 
      default: 
       writer.WriteValue(value); 
       break; 
     } 
    } 

    private void WriteObject(JsonWriter writer, object value) { 
     writer.WriteStartObject(); 
     var obj = value as IDictionary<string, object>; 
     foreach (var kvp in obj) { 
      writer.WritePropertyName(kvp.Key); 
      this.WriteValue(writer, kvp.Value); 
     } 
     writer.WriteEndObject(); 
    } 

    private void WriteArray(JsonWriter writer, object value) { 
     writer.WriteStartArray(); 
     var array = value as IEnumerable<object>; 
     foreach (var o in array) { 
      this.WriteValue(writer, o); 
     } 
     writer.WriteEndArray(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { 
     return ReadValue(reader); 
    } 

    private object ReadValue(JsonReader reader) { 
     while (reader.TokenType == JsonToken.Comment) { 
      if (!reader.Read()) throw new JsonSerializationException("Unexpected Token when converting IDictionary<string, object>"); 
     } 

     switch (reader.TokenType) { 
      case JsonToken.StartObject: 
       return ReadObject(reader); 
      case JsonToken.StartArray: 
       return this.ReadArray(reader); 
      case JsonToken.Integer: 
      case JsonToken.Float: 
      case JsonToken.String: 
      case JsonToken.Boolean: 
      case JsonToken.Undefined: 
      case JsonToken.Null: 
      case JsonToken.Date: 
      case JsonToken.Bytes: 
       return reader.Value; 
      default: 
       throw new JsonSerializationException 
        (string.Format("Unexpected token when converting IDictionary<string, object>: {0}", reader.TokenType)); 
     } 
    } 

    private object ReadArray(JsonReader reader) { 
     IList<object> list = new List<object>(); 

     while (reader.Read()) { 
      switch (reader.TokenType) { 
       case JsonToken.Comment: 
        break; 
       default: 
        var v = ReadValue(reader); 

        list.Add(v); 
        break; 
       case JsonToken.EndArray: 
        return list; 
      } 
     } 

     throw new JsonSerializationException("Unexpected end when reading IDictionary<string, object>"); 
    } 

    private object ReadObject(JsonReader reader) { 
     var obj = new Dictionary<string, object>(); 

     while (reader.Read()) { 
      switch (reader.TokenType) { 
       case JsonToken.PropertyName: 
        var propertyName = reader.Value.ToString(); 

        if (!reader.Read()) { 
         throw new JsonSerializationException("Unexpected end when reading IDictionary<string, object>"); 
        } 

        var v = ReadValue(reader); 

        obj[propertyName] = v; 
        break; 
       case JsonToken.Comment: 
        break; 
       case JsonToken.EndObject: 
        return obj; 
      } 
     } 

     throw new JsonSerializationException("Unexpected end when reading IDictionary<string, object>"); 
    } 

    public override bool CanConvert(Type objectType) { return typeof(IDictionary<string, object>).IsAssignableFrom(objectType); } 
} 
+0

Giải pháp này hoạt động rất tốt. Cảm ơn! – smdrager

+0

[Đây là giải pháp này trên bài viết khác] (http://stackoverflow.com/a/38029052/1062224) –

Các vấn đề liên quan