0

Je travaille sur une application qui enregistre des informations sur des exécutions individuelles (nom, date, distance, heure, type) dans une ObservableCollection.Erreur de désérialisation de JSON.net sur la charge du stockage isolé

J'ai un viewmodel configuré pour afficher cette information dans un LongListSelector. Je n'ai aucun problème pour obtenir les données dans le modèle, et aucun problème (au moins aucune erreur) en sauvegardant cette information - aussi longtemps que l'application fonctionne. Je reçois une exception lors du redémarrage de l'application et de tenter de charger cette information en désérialisant avec newtonsoft.json

Je reçois l'erreur en essayant de les données qui étaient auparavant sérialisés et sauvé à IsolatedStorageSettings.ApplicationSettings

le message d'erreur est: « System.Reflection.TargetInvocationException » dans mscorlib.ni.dll

Modifier répondre aux commentaires recherche plus d'informations Je vais travailler à obtenir le reste o f ça. Je suis nouveau dans le débogage lourd. La description de l'erreur est:

Newtonsoft.Json.JsonSerializationException: Impossible de désérialiser le tableau JSON en cours (par exemple [1,2,3]) dans le type 'Run_Ranger.ViewModels.RunSaveMain' car le type requiert un objet JSON (par exemple { "name": "value"}) pour désérialiser correctement. Pour corriger cette erreur, soit changer le JSON en un objet JSON (par exemple {"name": "valeur"}) ou changer le type désérialisé en un tableau ou un type qui implémente une interface de collection (par exemple iCollection, IList) être désérialisé à partir d'un tableau JSON. JsonArrayAttribute peut également être ajouté au type pour le forcer à désérialiser à partir d'un tableau JSON.

Path », ligne1, position1. À Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureArrayContract (lecteur JsonReader, type objectType, contrat JsonContract)

à ...

et plus je ne vois pas Pour une raison quelconque, je peux attraper l'exception et l'afficher dans une boîte de message sur l'émulateur (à partir de laquelle j'ai tapé ci-dessus, mais il est tronqué) mais quand j'utilise debug.writeline, je ne reçois rien dans la fenêtre de sortie (débogage) plus de: Exception levée: 'Newtonsoft.Json.JsonSerializationException' dans Newtonsoft.Json.DLL

Il se produit à cette ligne dans mon code. Je ne semble avoir aucun problème à sérialiser et à sauvegarder les données dans le stockage. Quand je débogue, je peux le voir là, la valeur ressemblant à cet exemple:

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

Je sérialisation et de l'enregistrer juste après chaque ajout d'un élément, comme ceci:

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

Je me suis demandé si il pourrait y avoir un problème à convertir les valeurs datetime, donc je l'ai couru à nouveau sans ceux-ci, et il s'est tout de même écrasé à la même ligne.

La classe est configuré comme ceci:

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

J'ai fait un tas de recherche et les seules erreurs comparables que je pouvais trouver semblaient provenir d'essayer de désérialiser données à l'extérieur dans les types de données erronées. Comme j'utilise JSON pour sérialiser les bons types de données directement à partir du modèle, je ne pense pas que ce soit mon problème, mais je suis bloqué pour ce qu'il pourrait être.

Quiconque a déjà vu ça?

+0

Quelle est la sortie complète 'ToString()' de l'exception, y compris le message, excep type d'erreur, trace de pile ** et exception interne **? 'TargetInvocationException' devrait avoir une exception interne. Vous pouvez "attraper" l'exception, puis la voir dans le débogueur ou l'enregistrer avec 'Debug.WriteLine (ex);' – dbc

+0

@dbc Edité ci-dessus avec plus d'informations sur l'erreur. Va comprendre comment en avoir plus. – WPNoviceCoder

Répondre

0

Vous sérialisez une liste de RunSaveItem ici:

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

Mais vous essayez de désérialiser un objet unique (pas une liste) de type RunSaveMain. Ces types sont incompatibles. Pire encore, Json.NET sérialise les collections sous forme de tableaux JSON tandis que d'autres POCO sont sérialisés en tant qu'objets JSON. La différence est expliqué dans le JSON standard:

  • Un tableau est une collection ordonnée de valeurs. Un tableau commence par [ (crochet de gauche) et se termine par ] (crochet de droite). Les valeurs sont séparées par , (virgule).

  • Un objet est un ensemble non ordonné de paires nom/valeur. Un objet commence par { (accolade gauche) et se termine par } (accolade droite).

Ce décalage explique le message d'exception que vous voyez:

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.

Au lieu de cela, vous devez désérialiser les données enregistrées en tant que collection du même type:

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

Merci. Je suis passé l'erreur de désérialisation maintenant, et ce qui est sauvé à isolerstorage apparaît à la relance. Mais j'ai mes signaux croisés quelque part parce qu'à l'exécution, je génère deux listes d'une manière ou d'une autre, et une seule peut se lier au LongListSelector. (Exécutions générées à l'exécution C'est l'héritage de l'utilisation de modèles intégrés et d'exemples de canaux 9 pour essayer de résoudre ce problème, et de les mélanger de manière très inégale.J'ai besoin d'un correctif à l'école viewModel. – WPNoviceCoder

+0

Merci encore, je l'ai fait fonctionner pleinement maintenant, comme je le soupçonnais, lors de l'exécution de "save", en créant "Items = new ObservableCollection ();" ailleurs, mais en faisant la même chose list "SavedRuns = new ObservableCollection ();" Je me suis lié à Items.Il était un désordre Votre conseil m'a permis de mieux comprendre et comprendre cela et j'espère porter cela à ma prochaine tâche: trier ces éléments par date, nom, distance, etc., appuyez sur le bouton – WPNoviceCoder

+0

oups, je pensais que j'avais, essayez à nouveau, merci.J'ai changé ma collection pour la liste donc le tri, etc. devrait être assez facile pour les prochaines étapes. – WPNoviceCoder