У меня есть метод расширения для сериализации строку 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);
...
В вашем случае будет выглядеть то, что вы знаете во время разработки все свойства и типы объектов. В моем случае мой json-объект будет содержать динамические свойства, поэтому я не могу явно указать имена свойств или их типы в классе. – Jeremy