自动序列化JSON以更正对象类型

时间:2016-03-17 20:57:18

标签: c# .net json

我有一个扩展方法将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没有我可以编写的严格属性集。

我有一个从REST API返回的JSON字符串,如下所示:

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

请注意,Comments属性包含一个转义的JSON字符串,它基本上是JSON字符串中的JSON字符串。

现在我有一个反序列化的扩展方法和一个对象模型,我可以反序列化:

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

正如您所看到的,这是一个两步过程,我需要通过明确指定Comment类类型来反序列化comment属性项。

有没有办法让deserializer在第一步中智能地将Properties集合中的项目反序列化为适当的类类型?因此,即使Record.Properties是Dictionary,对象也会是一个注释实例?

我通过在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);
...

1 个答案:

答案 0 :(得分: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;
}