JSON.net 从独立存储加载反序列化错误

JSON.net deserialization error on load from Isolated Storage

我正在开发一个应用程序,可以将有关个人跑步的信息(名称、日期、距离、时间、类型)保存到 ObservableCollection 中。

我已经设置了一个视图模型来在 LongListSelector 中显示此信息。我可以毫无问题地将数据导入模型,也没有问题(至少没有错误)保存该信息——只要应用程序是 运行。重新启动应用程序并尝试通过使用 newtonsoft.json

反序列化来加载该信息时出现异常

尝试将之前序列化并保存的数据 保存到 IsolatedStorageSettings.ApplicationSettings

时出现错误

错误信息是:'System.Reflection.TargetInvocationException' in mscorlib.ni.dll

编辑 回复寻求更多信息的评论 我会努力得到剩下的。我是重度调试的新手。错误描述为:

Newtonsoft.Json.JsonSerializationException:无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型 'Run_Ranger.ViewModels.RunSaveMain',因为该类型需要一个 JSON 对象(例如 {"name":"value"}) 正确反序列化。要修复此错误,请将 JSON 更改为 JSON 对象(例如 {"name":"value"})或将反序列化类型更改为数组或实现集合接口(例如 iCollection、IList),例如可以从 JSON 数组反序列化的 List。 JsonArrayAttribute 也可以添加到类型以强制它从 JSON 数组反序列化。

Path", line1, position1.at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract)

在...

还有更多我看不到的。出于某种原因,我可以捕获异常并将其显示在模拟器的消息框中(我在上面输入了它,但它被截断了)但是当我使用 debug.writeline 时,我没有在输出中得到任何东西window(调试)超过:抛出异常:'Newtonsoft.Json.JsonSerializationException' in Newtonsoft.Json.DLL

它出现在我代码中的这一行。

    private RunSaveMain GetSavedRunsFromMemory() // is this all I need to stick data into the model?
    {
        //ClearAll();
        RunSaveMain data;
        string dataFromAppSettings;

        if (IsolatedStorageSettings.ApplicationSettings.TryGetValue(SaveRunsKey, out dataFromAppSettings))
        {
            data = JsonConvert.DeserializeObject<RunSaveMain>(dataFromAppSettings); //<--- ERROR HERE
        }
        else
        {
            data = new RunSaveMain();
            data.Title = AppResources.SavedRuns;
        }

        return data;
    }

我似乎没有遇到序列化和保存数据的问题。当我调试时,我可以在那里看到它,值看起来像这个例子:

[{"RunName":"Steamtown Marathon 2015","RunType":"real","RunDistMiles":26.2,"RunDate":"2015-10- 18T00:00:00","RunTimeTotalSecs":10241.0},{"RunName":"Marine Corps Marathon 2015","RunType":"real","RunDistMiles":26.2,"RunDate":"2015-10-25T00:00:00","RunTimeTotalSecs":10500.0}]

我在每次添加项目后立即序列化并保存它,如下所示:

private void RunNameCompleted(object sender, string runName, string runType)
    {
        // name string has already been checked 
        // create a rundata object
        // put in as much info as we want
        RunSaveItem RunToSave = new RunSaveItem();
        RunToSave.RunName = runName; // various values passed in
        RunToSave.RunDate = CurrentPaceMath.Rundate;
        RunToSave.RunType = runType;
        RunToSave.RunTimeTotalSecs = CurrentPaceMath.TimeTotalSecsIn;
        RunToSave.RunDistMiles = CurrentPaceMath.MilesIn;
        App.RunSaveItemView.Items.Add(RunToSave); // // add the rundata to app.viewmodels.runmodel

        // save the list of runs to isolatedstorage.applicationSettings                                          
        var data = JsonConvert.SerializeObject(App.RunSaveItemView.Items);
        IsolatedStorageSettings.ApplicationSettings[RunSaveMain.SaveRunsKey] = data;
        IsolatedStorageSettings.ApplicationSettings.Save();

        NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.RelativeOrAbsolute));
    }

我想知道转换日期时间值是否可能存在问题,所以我 运行 没有那些,它仍然在同一行崩溃。

class是这样设置的:

public class RunSaveItem : INotifyPropertyChanged
{
    private string _runName;
    /// <summary>
    /// Name of the run
    /// </summary>
    public string RunName
    {
        get
        {
            return _runName;
        }
        set
        {
            if (value != _runName)
            {
                _runName = value;
                NotifyPropertyChanged("RunName");
            }
        }
    }

    private string _runType;
    /// <summary>
    /// Type of run
    /// </summary>
    public string RunType
    {
        get
        {
            return _runType;
        }
        set
        {
            if (value != _runType)
            {
                _runType = value;
                NotifyPropertyChanged("RunType");
            }
        }
    }

    private double _runDistMiles;
    /// <summary>
    /// Run distance in miles
    /// </summary>
    public double RunDistMiles
    {
        get
        {
            return _runDistMiles;
        }
        set
        {
            if (value != _runDistMiles)
            {
                _runDistMiles = value;
                NotifyPropertyChanged("RunDistMiles");
            }
        }
    }

    private DateTime _runDate;
    /// <summary>
    /// Date of the run. There will be no time, or rather, time = 00:00:00 as it's selected with a datepicker.
    /// </summary>
    public DateTime RunDate
    {
        get
        {
            return _runDate;
        }
        set
        {
            if (value != _runDate)
            {
                _runDate = value;
                NotifyPropertyChanged("RunDate");
            }
        }
    }

    private double _runTimeTotalSecs;
    /// <summary>
    /// Duration of the run expressed in seconds
    /// </summary>
    public double RunTimeTotalSecs
    {
        get
        {
            return _runTimeTotalSecs;
        }
        set
        {
            if (value != _runTimeTotalSecs)
            {
                _runTimeTotalSecs = value;
                NotifyPropertyChanged("RunTimeTotalSecs");
            }
        }
    }

我进行了大量搜索,我能找到的唯一类似错误似乎源于试图将外部数据反序列化为错误的数据类型。因为我一开始就使用 JSON 直接从模型中序列化正确的数据类型,所以我不认为这是我的问题,但我对它可能是什么感到困惑。

有人以前看过这个吗?

您正在此处序列化 RunSaveItemlist

    // save the list of runs to isolatedstorage.applicationSettings                                          
    var data = JsonConvert.SerializeObject(App.RunSaveItemView.Items);
    IsolatedStorageSettings.ApplicationSettings[RunSaveMain.SaveRunsKey] = data;
    IsolatedStorageSettings.ApplicationSettings.Save();

但是您正在尝试反序列化 类型 RunSaveMain 的单个对象(不是列表)。这些类型不一致。更糟糕的是,Json.NET 将集合序列化为 JSON 数组,而其他 POCO 序列化为 JSON 对象。 JSON standard:

中解释了差异
  • 数组是值的有序集合。数组以 [(左括号)开始,以 ](右括号)结束。值由 ,(逗号)分隔。

  • 对象是 name/value 对的无序集合。对象以 {(左大括号)开始,以 }(右大括号)结束。

这种不匹配导致您看到异常消息:

Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Run_Ranger.ViewModels.RunSaveMain' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.

相反,您需要将保存的数据反序列化为相同类型的集合:

private List<RunSaveItem> GetSavedRunsFromMemory()
{
    //ClearAll();
    List<RunSaveItem> data;
    string dataFromAppSettings;

    if (IsolatedStorageSettings.ApplicationSettings.TryGetValue(SaveRunsKey, out dataFromAppSettings))
    {
        data = JsonConvert.DeserializeObject<List<RunSaveItem>>(dataFromAppSettings); 
    }
    else
    {
        data = new List<RunSaveItem>();
    }

    return data;
}