2012-07-19 6 views
14

Newtonsoft JSON.NET을 사용하도록 이전 작업을 변환하려고합니다. System.Web.Script.Serialization.JavaScriptSerializer.Deserialize 메소드를 사용하는 기본 처리 (예 : 대상 유형을 지정하지 않은 경우)는 내부 오브젝트에 Dictionary<string,object>을 리턴합니다.JSictionary를 재귀 적으로 IDictionary로 역 직렬화합니다. <string, object>

실제로는 ExpandoObjects에서 사용되는 기본 유형이기 때문에 JSON에 실제로 유용한 기본 유형이며 동적 유형에 대해 가장 현명한 내부 구현입니다.

나는, 예컨대 :

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

JSON.NET 올바르게 바깥 쪽 오브젝트 구조를 직렬화합니다이 유형을 지정하지만, 어떤 내부 구조에 대한 JObject 유형을 반환합니다. 필자가 정말로 필요로하는 것은 내부 구조체 구조에 동일한 외부 구조체를 사용하는 것입니다.

반환되는 가장 바깥 쪽 형식뿐만 아니라 내부 개체에 사용할 형식을 지정하는 방법이 있습니까?

답변

7

Json을 사용하여 복잡한 객체를 비 직렬화 할 때 JsonSerializer 설정을 매개 변수로 추가해야합니다. 이렇게하면 모든 내부 유형이 제대로 직렬화 복원됩니다. 개체를 직렬화 할 때

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

, 당신은 SerializerSettings를 사용할 수 있습니다

string json= JsonConvert.SerializeObject(myObject, _jsonSettings) 

을 그럼 당신은 직렬화 복원되어, 사용 : 당신이 직렬화 할 때 또한

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

이,에 JsonSerializerSettings 추가 귀하의 SerializeObject (개체, 설정)

편집 : 또한 변경할 수 있습니다 그는 필요한 경우 TypeNameHandling 및 TypeNameAssemblyFormat을 사용합니다. 나는 각각의 객체를 각각 'All'과 'Full'로 설정하여 복잡한 객체가 의심없이 직렬화되고 직렬화가 적절히 해제되도록합니다. 그러나 intellisense는 다른 대안을 제공합니다.

+0

정답입니까? –

+1

@LukePuplett 질문에 따라 이것이 정확하다고 생각하지 않습니다. –

+0

질문에 따라 이것이 올바른 대답은 아닙니다. –

15

json.Net에서 json 문자열을 비 직렬화하려면 중첩 된 객체와 배열을 비 직렬화하는 작업을 포함하여 IDictionary<string, object>에 추가하면 Json.Net에서 제공하는 JsonConverter 추상 클래스에서 파생 된 사용자 정의 클래스를 만들어야합니다.

파생 된 내용은 JsonConverter이며 json과의 개체 작성 방법을 구현 한 것입니다.

이 같은 사용자 정의 JsonConverter를 사용할 수 있습니다

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); } 
} 
: 여기
var o = JsonConvert.DeserializeObject<IDictionary<string, object>>(json, new DictionaryConverter()); 

나는 당신이 당신의 문제의 개요와 같은 목표를 달성하기 위해 과거에 성공을 사용한 사용자 정의 JsonConverter입니다
+0

이 솔루션은 훌륭하게 작동합니다. 감사! – smdrager

+0

[여기에 다른 솔루션에 대한 해결책입니다] (http://stackoverflow.com/a/38029052/1062224) –

관련 문제