【问题标题】:Json.net deserializing dictionary containing dictionary with value of dataTableJson.net 反序列化字典,其中包含具有 dataTable 值的字典
【发布时间】:2012-06-08 17:37:16
【问题描述】:

我对编程很陌生(在课堂环境之外)。

我正在开发一个具有插件的应用程序。每个插件打包/解包它的状态(作为字典)并将自己添加到包含所有打包状态的字典中。我正在使用 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。然后,当在 Unpack 中时,它是带有 : 分隔符的值中的实际数据表。

我会提供屏幕截图,但我还没想好怎么做。任何想法我错过了什么? 谢谢!

【问题讨论】:

  • 问题是DataTable 以一种特殊的方式序列化,它有自己的内置转换器,可以将其转换为数组(这意味着它不包含类型信息)。我不确定如何解决这个问题。

标签: c# serialization json.net


【解决方案1】:

保存项目时,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);

希望这可以帮助任何寻找答案的人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-19
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多