2012-06-08 70 views
2

我對編程相當新(在教室環境之外)。Json.net反序列化字典包含字典值dataTable

我正在研究一個有插件的應用程序。每個插件打包/解包它的狀態(作爲字典),併發送自己以將其添加到包含所有打包狀態的字典中。我使用Json.Net來序列化/反序列化,並根據項目是保存還是打開,將每個插件傳遞給自己的類進行打包/解壓縮。

我遇到的問題是,當我的第一個插件得到它的它的字典版本而打包狀態來解壓,我開始通過每個屬性,第一個屬性(第一項在字典中)的羣體恢復會是一個DataTable 。我收到一個錯誤消息:

Unable to cast object of type 'Newtonsoft.Json.Linq.JArray' to 
type 'System.Data.DataTable'. 

這是我的序列化代碼。

IDictionary<string, IDictionary<string, object>> pluginStates = 
      new Dictionary<string, IDictionary<string, object>>(); 
signaller.RaiseSaveRequest(pluginStates); //gets all of the plugins' packedState 

JsonSerializer serializer = new JsonSerializer(); 
serializer.ObjectCreationHandling = ObjectCreationHandling.Replace; 
serializer.TypeNameHandling = TypeNameHandling.All; 

using (StreamWriter sw = new StreamWriter(strPathName)) 
using (JsonWriter writer = new JsonTextWriter(sw)) 
{ 
    serializer.Serialize(writer, pluginStates); 
} 

和反序列化。

IDictionary<string, IDictionary<string, object>> pluginStates = 
      new Dictionary<string, IDictionary<string, object>>(); 

JsonSerializer serializer = new JsonSerializer(); 
serializer.ObjectCreationHandling = ObjectCreationHandling.Replace; 
serializer.TypeNameHandling = TypeNameHandling.All; 

StreamReader sr = new StreamReader(fullName); 
JsonTextReader reader = new JsonTextReader(sr); 
string json = sr.ReadToEnd(); 
pluginStates = serializer.Deserialize<IDictionary<string, IDictionary<string, Object>>>(reader); 
pluginStates = JsonConvert.DeserializeObject<IDictionary<string, IDictionary<string, Object>>>(json); 
sr.Close(); 
reader.Close(); 

signaller.UnpackProjectState(pluginStates); 

我試着看在NewtonSoft.Json文檔,但是我不太瞭解它,如何讓它在我的代碼工作。我想我需要在插件獲取打包狀態解壓後,使用轉換器或解析進行一些操作。當它被打包時,插件的第一個字典條目被保存爲DataTable。然後,當在解壓縮時,它是具有:分隔符值的實際dataTable。

我會提供屏幕截圖,但我還沒有想出如何做到這一點。任何想法我失蹤了? 感謝!

+0

問題是'DataTable'是以特殊方式序列化的,它有它自己的內置轉換器將它轉換爲一個數組(這意味着它不包含類型信息)。我不知道如何解決這個問題。 – svick

回答

0

保存項目時,ProjMngr將獲取打包的pluginStates字典。我遍歷pluginStates字典中的每個字典(插件),並創建一個包含鍵,值(json字符串版本)和鍵值(.net類型)的字典。將這些添加到數組中,並將數組放入最終的projectState字典中,該字典將被序列化。這是代碼。

signaller.RaiseSaveRequest(pluginStates); <----has all plugin's packedState 

//loop through plugins to get values and types 
Dictionary<string, object> dictProjectState = new Dictionary<string, object>(); 

foreach (KeyValuePair<string,IDictionary<string,object>> plugin in pluginStates) 
{ 
    //holds jsonRepresented values 
    Dictionary<string, object> dictJsonRep = new Dictionary<string, object>(); 
    //holds object types 
    Dictionary<string, object> dictObjRep = new Dictionary<string, object>(); 
    object[] arrayDictHolder = new object[2]; //holds all of the dictionaries 

    string pluginKey = plugin.Key; 

    IDictionary<string, object> pluginValue = new Dictionary<string, object>(); 
    pluginValue = plugin.Value; 

    foreach (KeyValuePair<string, object> element in pluginValue) 
    { 
     string jsonRepresentation = JsonConvert.SerializeObject(element.Value); 
     object objType = element.Value.GetType(); 
     dictJsonRep.Add(element.Key, jsonRepresentation); 
     dictObjRep.Add(element.Key, objType); 
    } 
    arrayDictHolder[0] = dictJsonRep; 
    arrayDictHolder[1] = dictObjRep; 
    dictProjectState.Add(pluginKey, arrayDictHolder); 
} 

JsonSerializer serializer = new JsonSerializer(); 

using (StreamWriter sw = new StreamWriter(strPathName)) 
using (JsonWriter writer = new JsonTextWriter(sw)) 
{ 
    serializer.Serialize(writer, dictProjectState); 
} 

然後,打開項目時,我做了同樣的事情,相反,以獲得pluginState回到它的原始狀態歡送每個插件。在發送前使用該類型以確保類型正確。意識到我不得不反序列化幾次,這是令人驚訝的。我無法擺脫Jarray或Jobject。但是,這工作。這是我打開的方式。

IDictionary<string, IDictionary<string, object>> pluginStates = new Dictionary<string, IDictionary<string, object>>(); 

StreamReader sr = new StreamReader(fullName); 
JsonTextReader reader = new JsonTextReader(sr); 
string json = sr.ReadToEnd(); 

var dictProjectState = JsonConvert.DeserializeObject<Dictionary<string, object>>(json); 
sr.Close(); 
reader.Close(); 

foreach (var projectStatePair in dictProjectState) 
{ 
    string pluginKey = projectStatePair.Key; //key in pluginStates dict 
    Dictionary<string, object> dictJsonRep = new Dictionary<string, object>(); 
    Dictionary<string, object> dictObjRep = new Dictionary<string, object>(); 
    Dictionary<string, object> pluginValues = new Dictionary<string, object>(); 

    string stpluginValue = projectStatePair.Value.ToString(); 

    Newtonsoft.Json.Linq.JArray ja = (Newtonsoft.Json.Linq.JArray)JsonConvert.DeserializeObject(stpluginValue); 

    object[] arrayHolder = ja.ToObject<object[]>(); 

    string strArray0 = arrayHolder[0].ToString(); 
    string strArray1 = arrayHolder[1].ToString(); 

    dictJsonRep = JsonConvert.DeserializeObject<Dictionary<string, object>>(strArray0); 
    dictObjRep = JsonConvert.DeserializeObject<Dictionary<string, object>>(strArray1); 

    foreach (var pair in dictJsonRep) 
    { 
     string strVariableKey = pair.Key; 
     object objType = dictObjRep[pair.Key]; 
     string jsonRep = (string)pair.Value; 
     Type jsonType = Type.GetType(objType as string); 
     object jsonReprValue = null; 
     jsonReprValue = JsonConvert.DeserializeObject(jsonRep, jsonType); 
     pluginValues.Add(strVariableKey, jsonReprValue); 
    } 
    pluginStates.Add(pluginKey, pluginValues); 
} 

signaller.UnpackProjectState(pluginStates); 

希望這有助於任何人尋找答案。

相關問題