2011-04-30 5 views
3

J'utilise le sérialiseur json.net de newton. En désérialisant le json à 'The Fox'; il entre dans le ctor protégé et obtient les valeurs de propriété par défaut. Mais pas les valeurs de propriété dans la chaîne json. Puis-je résoudre ce problème sans utiliser dto ou tout autre framework de mappeur?Désérialisation Objet construit protégé de json

class TheFox 
    { 

    string _Id; 
    string _Name; 

    protected TheFox() 
    { 
     _Id = "Default Id"; 
     _Name = "Default Name"; 
    } 

    public TheFox(string id, string name) : this() 
    { 
     _Name = name; 
     _Id = id; 
    } 

    public string Id 
    { 
     get { return _Id; } 
    } 

    public string Name 
    { 
     get { return _Name; } 
    } 
} 

C'est le test:

 var fox = new TheFox("FoxId", "FoxTail"); 
     var json = JsonConvert.SerializeObject(fox); 
     Console.WriteLine(json); 

     var settings = new JsonSerializerSettings() 
     { 
      ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor 
     }; 

     var returned = JsonConvert.DeserializeObject<TheFox> (json, settings); 

     Assert.IsTrue (returned.Id != "Default Id"); 
     Assert.IsTrue (returned.Name != "Default Name"); 
+0

Il est étrange que tant de désérialiseurs ne prennent pas en charge les constructeurs paramétrés. – CodesInChaos

Répondre

0

Vérifié la source de json.net et il n'y a aucun moyen pour le moment. Parce que si la propriété donnée est en lecture seule, elle ignore le réglage de l'étape de valeur. peut avoir besoin d'une fonction de remplissage de champ interne.

private void SetPropertyValue(JsonProperty property, JsonReader reader, object target) 
    { 
     // bla.. bla.. bla.. 
     if (!property.Writable && !useExistingValue) 
     { 
     reader.Skip(); 
     return; 
     } 

Cette méthode est mauvaise, il a besoin d'un objet instancié pour remplir, mais il fonctionne.

var a = new TheFox("x", "y"); 
var json = JsonConvert.SerializeObject(a); 
Console.WriteLine(json); 

var returned = JsonConvert.DeserializeAnonymousType(json, new TheFox("q", "a")); 

Assert.That(a.Id, Is.EqualTo(returned.Id)); 
Assert.That(a.Name, Is.EqualTo(returned.Name)); 
+0

Êtes-vous fortement opposé à l'utilisation de setters protégés ou même privés pour ces propriétés? Cela vous serait utile si vous utilisiez l'annotation [JsonProperty]. – Konstantin

-2

Votre classe ne convient pas pour le fonctionnement du côté client. Vous devez utiliser DataContractAttribute pour la classe et l'attribut DataMemberAttribute pour les membres que vous souhaitez sérialiser.

+0

Je ne fais que désérialiser mon objet avec un cadre. Je n'ai pas d'affaire avec wcf. –

0
class TheFox 
    { 
     string _Id; 
     string _Name; 

     protected TheFox() : this("Default Id", "Default Name") 

     public TheFox(string id, string name) 
     { 
     _Name = name; 
     _Id = id; 
     } 

     public string Id 
    { 
        get { return _Id; } 
    } 

    public string Name 
    { 
        get { return _Name; } 
    } 
} 

Ceci devrait permettre le même usage mais offre une comparabilité avec newton.

+0

les deux de votre constructeur s'appellent récursivement. J'ai enlevé ctor paramétrable et exécuter le test. Non, le résultat n'a pas changé. toujours les valeurs par défaut. –

+0

Désolé, c'est la dernière fois que j'essaie d'écrire du code sur l'iPad! Correction des erreurs –

Questions connexes