2016-03-17 4 views
2

У меня есть метод расширения для сериализации строку JSON к объектуAuto сериализация JSON исправить тип объекта

/// <summary> 
/// Deserialize JSON formatted string to an object of a specified type 
/// </summary> 
/// <typeparam name="T">Object type to deserialize</typeparam> 
/// <param name="sJSON">JSON formatted string to deserialize</param> 
/// <returns>Returns an instance of an object</returns> 
public static T FromJSON<T>(this string sJSON) where T : new() 
{ 
    T oValue; 

    using (System.IO.MemoryStream strJSON = new System.IO.MemoryStream()) 
    { 
     using (System.IO.StreamWriter swJSON = new System.IO.StreamWriter(strJSON)) 
     { 
      swJSON.Write(sJSON); 
      swJSON.Flush(); 

      strJSON.Seek(0, System.IO.SeekOrigin.Begin); 

      System.Runtime.Serialization.Json.DataContractJsonSerializer ser = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T)); 
      oValue = (T)ser.ReadObject(strJSON); 

      return oValue; 
     } 
    } 
} 

Я несколько классов, определенным для представления объектов, которые я хочу десериализации строки JSON в:

/// <summary> 
/// Represents a record and it's properties 
/// </summary> 
[DataContract] 
public class Record 
{ 
    /// <summary> 
    /// Dictionary of properties for the record 
    /// </summary> 
    [DataMember(Name = "properties")] 
    public Dictionary<string, object> Properties { get; set; } 
} 

[DataContract] 
public class Comments 
{   
    [DataMember(Name = "Comment")] 
    public CommentItem[] CommentCollection { get; set; } 

    public static Comments FromJSON(string sJSON) 
    { 
     return sJSON.FromJSON<Comments>(); 
    } 
} 

[DataContract] 
public class CommentItem 
{ 
    [DataMember(Name = "CommentId")] 
    public string CommentId {get; set;} 

    [DataMember(Name = "CommentBody")] 
    public string CommentBody { get; set; } 
} 

Только примечание о том, что я использую свойство Dictionary, потому что поставщики REST API, которые я потребляю, не имеют строгого набора свойств, которые я могу кодировать.

У меня есть строка JSON вернулась из REST API следующим образом:

{ 
    "properties" : {  
     "Id" : "12644", 
     "Description" : "Test", 
     "Comments" : "{\"Comment\":[{\"CommentId\":\"cfe6235f-40ee-421d-807f-30315a9f1e08\",\"CommentBody\":\"Test 123\"},{\"CommentId\":\"8d89eef6577e22762650ee5225eb9402ca2f\","CommentBody\":\"Test XYZ\"}]}" 
    } 
} 

Обратите внимание, что свойство Комментариев содержит сбежавшую строку JSON, это в основном строка JSON в виде строки JSON.

Так что теперь у меня есть метод расширения для десериализации и объектная модель, я могу десериализацию:

Record r = sMyJSON.FromJSON<Record>(); 
Comments c = r.Properties["Comments"].ToString().FromJSON<Comments>(); 

Как вы можете видеть, это два шага, и я должен десериализацией комментарий свойства элемента задав тип класса Comment явно.

Есть ли способ заставить десериализатор разумно десериализовать элементы в коллекции свойств на соответствующие типы классов в течение первого шага? Так что, хотя Record.Properties - это словарь, объект будет, в данном случае, экземпляром комментариев?

Я попытался это, задав известные типы в JSON сериализатором:

... 
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T), new DataContractJsonSerializerSettings() 
    { 
     UseSimpleDictionaryFormat = true, 
     KnownTypes = new Type[] 
     { 
      typeof(ObjectModel.Comments), 
      typeof(string[]), 
      typeof(List<string>), 
      typeof(int[]), 
      typeof(List<int>) 
     } 
    }); 
    return (T)ser.ReadObject(strJSON); 
... 

ответ

0

Я не уверен, если это отвечает на ваш вопрос, но вот как я сериализации и десериализации пользовательские классы с использованием Json.NET:

public class AssignmentHistory 
{ 
    public DateTime WeekOfAssignment { get; set; } 
    public int TalkType { get; set; } 
    public int StudentID_FK { get; set; } 
    public int AssistantID_FK { get; set; } 
    public int CounselPoint { get; set; } 
    public bool HasBeenEmailed { get; set; } 
    public bool SlipHasBeenPrinted { get; set; }   
} 

public static string ASSIGNMENT_TYPES_FILENAME = @"C:\AYttFMApp\AYttFMScheduler\AssignmentTypes.json"; 
. . . 
public static List<AssignmentHistory> AssignmentHistList; 
. . . 
public static void SerializeAssignmentHistFile(string fileStorageLoc) 
{ 
    var jsonAssignmentHist = JsonConvert.SerializeObject(AssignmentHistList); //_assignmentHistList); 
     System.IO.File.WriteAllText(fileStorageLoc, jsonAssignmentHist); 
} 

public static List<AssignmentHistory> DeserializeAssignmentHistFile() 
{ 
    if (!System.IO.File.Exists(ASSIGNMENT_HISTORY_FILENAME)) 
    { 
     var assignmentFile = 
System.IO.File.Create(ASSIGNMENT_HISTORY_FILENAME); 
     assignmentFile.Close(); 
     return null; 
    } 

    var assignmentHistFile = 
System.IO.File.ReadAllText(ASSIGNMENT_HISTORY_FILENAME); 
    var assignmentHistDeserialized = 
JsonConvert.DeserializeObject<List<AssignmentHistory>>(assignmentHistFile); 

    if (null != assignmentHistDeserialized) return 
assignmentHistDeserialized; 

    var assignmentHistoryList = new List<AssignmentHistory>(); 
    return assignmentHistoryList; 
} 
+0

В вашем случае будет выглядеть то, что вы знаете во время разработки все свойства и типы объектов. В моем случае мой json-объект будет содержать динамические свойства, поэтому я не могу явно указать имена свойств или их типы в классе. – Jeremy

Смежные вопросы