Bien désérialiser mais pas sérialiser avec json.net
Nous avons quelques fichiers de configuration qui ont été générés par la sérialisation des objets C# avec Json.net.
Nous aimerions migrer une propriété de la sérialisés classe loin d'être une simple enum d'une propriété dans une propriété de classe.
Un moyen facile de le faire, serait de laisser la vieille enum bien sur la classe, et prendre des dispositions pour Json.net pour lire cette propriété lorsque l'on charge le fichier config, mais pas à l'enregistrer de nouveau la prochaine fois que nous sérialiser l'objet. Nous allons faire face à la production de la nouvelle classe à partir de l'ancien enum séparément.
Est-il un moyen simple de marque (avec attributs) d'une propriété d'un objet de C#, de sorte que Json.net il sera ignoré SEULEMENT lors de la sérialisation, mais assister lors de la désérialisation?
- Que penser d'un convertisseur personnalisé : vous pouvez l'utiliser comme un attribut sur votre propriété, remplacer ReadJson et WriteJson avec différents leurs comportements, non ? Exemple (pas exactement ce que vous avez besoin, mais...) weblogs.asp.net/thangchung/archive/2010/08/26/...
- attribut OnDeserialized peut être un travail autour de vous
- Ne pourrait-il pas être possible à l'aide de la " [JsonIgnore]' attribut?? james.newtonking.com/archive/2009/10/23/...
- Êtes-vous en mesure de préciser comment cela peut être utilisé que dans une seule direction, comme par le dernier paragraphe de la q?
- Il est possible d'utiliser [JsonIgnore] en combinaison avec un secondaire privé setter qui est décoré avec un [JsonProperty] attribut. Il ya un couple d'autres solutions simples ainsi. J'ai ajouté une description détaillée.
- Après 1 an, ma réponse ci-dessous n'a qu'un seul vote, mais si vous retirez de l'obtenir; à partir de la propriété, le JSON serialiser ne pouvez pas le lire, donc il ne pourra plus exporter de l'ancienne valeur.
Vous devez vous connecter pour publier un commentaire.
Il ya en fait plusieurs assez simple approches que vous pouvez utiliser pour obtenir le résultat que vous souhaitez.
Supposons, par exemple, que vous avez vos classes actuellement défini comme ceci:
Et vous souhaitez le faire:
Pour obtenir ceci:
Approche 1: Ajouter un ShouldSerialize méthode
Json.NET a la capacité d'conditionnellement sérialiser des propriétés par la recherche de correspondant
ShouldSerialize
méthodes dans la classe.Pour utiliser cette fonction, ajouter un booléen
ShouldSerializeBlah()
méthode de classe oùBlah
est remplacé par le nom de la propriété que vous ne voulez pas sérialiser. Faire de la mise en œuvre de cette méthode retourne toujoursfalse
.Remarque: si vous aimez cette approche, mais vous ne voulez pas à compliquer l'interface publique de la classe par l'introduction d'un
ShouldSerialize
méthode, vous pouvez utiliser unIContractResolver
de faire la même chose par programmation. Voir Conditionnel Propriété De Sérialisation dans la documentation.Approche 2: Manipuler du JSON avec JObjects
Au lieu d'utiliser
JsonConvert.SerializeObject
à faire de la sérialisation, charger la configuration d'un objet dans unJObject
, puis il suffit de supprimer les indésirables de la propriété de l'JSON avant de l'écrire. C'est juste un couple de lignes de code supplémentaires.Approche 3: Intelligent (ab)utilisation d'attributs
[JsonIgnore]
attribut de la propriété que vous ne voulez pas être sérialisé.[JsonProperty]
attribut à l'autre setter, de lui donner le même JSON nom que l'original de la propriété.Ici est la version révisée de la
Config
classe:JsonPropertyAttribute
, à partir de C# 6.0, vous pouvez utiliser lenameof
mot-clé au lieu d'utiliser des "chaînes magiques". Cela rend le refactoring d'un beaucoup plus facile et infaillible de plus, si vous manquez de renommer toutes les occurrences, le compilateur vous préviendra de toute façon. À l'aide de @Brian exemple, l'utilisation serait la suivante :[JsonProperty(nameof(ObsoleteSetting))]
J'aime coller avec des attributs sur ce, voici la méthode que j'utilise quand avoir à désérialiser une propriété, mais pas sérialiser ou vice versa.
ÉTAPE 1 - Créer l'attribut personnalisé
ÉTAPE 2 - création d'un Contrat personnalisé Reslover
ÉTAPE 3 - Ajouter l'attribut où la sérialisation n'est pas nécessaire, mais la désérialisation est
ÉTAPE 4 - Utiliser
Espérons que cette aide! Aussi il est intéressant de noter que ce sera aussi ignorer les propriétés lors de la Désérialisation arrive, quand je suis derserializing je viens d'utiliser le convertisseur de manière conventionnelle.
GetSerializableMembers
plutôt que de remplacer entièrement?return base.GetSerializableMembers(objectType).Where(pi => !Attribute.IsDefined(pi, typeof(JsonIgnoreSerializationAttribute))).ToList();
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { ContractResolver = new JsonPropertiesResolver() }
Pour toute situation où il est acceptable d'avoir votre désérialisation-seulement du bien être marqué interne, il y a une remarquable solution simple, qui ne dépend pas des attributs à tous. Il suffit de marquer la propriété interne, mais d'un ensemble public:
Cette résultats dans le bon désérialisation utilisant les paramètres par défaut/résolveurs/etc., mais la propriété est dépouillé de sérialisé sortie.
Utiliser le setter de la propriété:
Espérons que cette aide.
IgnoreOnSerializing
, égal à la propriété. Je recommande d'utilisernameof(IgnoreOnSerializing)
pour éviter la magie de la chaîne, en cas de changement de nom.Après j'ai passé un assez long temps de recherche de la façon de marquer une propriété de la classe de Serializable et PAS Sérialisable j'ai trouvé qu'il n'y a pas une telle chose à faire qu'à tous; alors je suis venu avec une solution qui combine deux bibliothèques différentes ou de sérialisation techniques (Système d'.Moment de l'exécution.La sérialisation.Json & Newtonsoft.Json) et il a travaillé pour moi comme la suivante:
puis Sérialiser l'aide de "Newtonsoft.Json.JsonConvert.SerializeObject" et la " Dé-Sérialiser l'aide de "Système.Moment de l'exécution.La sérialisation.Json.DataContractJsonSerializer".
Espère que ça aide ...
avec référence à @ThoHo de la solution, à l'aide de l'incubateur est en fait tout ce qui est nécessaire, sans balises.
Pour moi j'ai déjà eu un seul Id de référence, que j'ai voulu charger et ajouter à la nouvelle collection de Id de référence. Par la modification de la définition de l'Id de référence pour contenir uniquement une méthode de définition, ce qui a ajouté de la valeur à la nouvelle collection. Json ne peut pas écrire la valeur de retour si la Propriété n'ont pas obtenir; méthode.
Cette classe est maintenant compatible avec la version précédente et seulement d'économiser de l' RefIds pour les nouvelles versions.
De construire sur Tho Ho réponse, cela peut aussi être utilisé pour les champs.
Si vous utilisez JsonConvert,IgnoreDataMemberAttribute est ok.Ma bibliothèque standard pas refrence Newton.Json,et je l'utilise [IgnoreDataMember] pour objet de contrôle de sérialiser.
De Newton.net document d'aide.
Selon l'endroit où l'application de ce lieu et si c'est juste une propriété, un manuel façon dont vous pouvez le faire en définissant la valeur de la propriété à la valeur null et puis, dans le modèle, vous pouvez spécifier que le bien être ignoré si la valeur est null:
Si vous travaillez sur un ASP.NET Base web app, vous pouvez définir globalement ce pour toutes les propriétés de tous les modèles par la définition de cette dans votre Démarrage.cs fichier:
La façon la plus simple que j'ai trouvé de cette écriture est d'inclure cette logique dans votre IContractResolver.
Exemple de code ci-dessus lien copié ici pour la postérité:
Toutes les réponses sont bonnes, mais cette approche semble être la façon la plus propre. J'ai effectivement mis en œuvre en regardant un attribut de la propriété pour SkipSerialize et SkipDeserialize de sorte que vous pouvez marquer jusqu'à toute la classe que vous contrôlez. Excellente question!