来自隔离存储的负载的JSON.net反序列化错误

时间:2016-04-29 00:56:49

标签: c# windows-phone-8 json.net deserialization isolatedstorage

我正在开发一个应用程序,用于将有关个别运行(名称,日期,距离,时间,类型)的信息保存到ObservableCollection中。

我已经设置了一个viewmodel来在LongListSelector中显示这些信息。我没有问题将数据导入模型,并且没有问题(至少没有错误)保存该信息 - 只要应用程序正在运行。重新启动应用程序并尝试通过使用newtonsoft.json反序列化来加载该信息时出现异常

我在尝试将之前序列化并保存的数据时遇到错误

错误消息是: mscorlib.ni.dll中的“System.Reflection.TargetInvocationException”

编辑回复评论,寻求更多信息 我会努力完成剩下的工作。我是重新调试的新手。错误描述是:

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

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

at ...

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

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

    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));
    }

我想知道转换日期时间值是否存在问题,所以我在没有它们的情况下再次运行它,它仍然在同一行崩溃。

课程设置如下:

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直接从模型中序列化正确的数据类型,所以我不认为这是我的问题,但我不知道它可能是什么。

之前有人见过这个吗?

1 个答案:

答案 0 :(得分:0)

您正在序列化RunSaveItem列表

    // 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

中解释
  • 数组是有序的值集合。数组以[(左括号)开头,以](右括号)结尾。值以,(逗号)分隔。

  • 对象是一组无序的名称/值对。对象以{(左大括号)开头,以}(右大括号)结束。

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

  

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;
}