Nous avons quelques fichiers de configuration qui ont été générés en sérialisant des objets C # avec Json.net.
Nous aimerions migrer une propriété de la classe sérialisée loin d'être une simple propriété enum vers une propriété de classe.
Un moyen simple de le faire serait de laisser l'ancienne propriété enum sur la classe et de faire en sorte que Json.net lise cette propriété lorsque nous chargeons la configuration, mais pas de la sauvegarder lors de la prochaine sérialisation de l'objet. Nous traiterons la génération de la nouvelle classe à partir de l'ancienne énumération séparément.
Existe-t-il un moyen simple de marquer (par exemple avec des attributs) une propriété d'un objet C #, de sorte que Json.net l'ignore UNIQUEMENT lors de la sérialisation, mais s'en occupe lors de la désérialisation?
Réponses:
Il existe en fait plusieurs approches assez simples que vous pouvez utiliser pour obtenir le résultat souhaité.
Supposons, par exemple, que vos classes soient actuellement définies comme ceci:
Et vous voulez faire ceci:
Pour obtenir ceci:
Approche 1: ajouter une méthode ShouldSerialize
Json.NET a la capacité de sérialiser conditionnellement les propriétés en recherchant les
ShouldSerialize
méthodes correspondantes dans la classe.Pour utiliser cette fonctionnalité, ajoutez une
ShouldSerializeBlah()
méthode booléenne à votre classe oùBlah
est remplacé par le nom de la propriété que vous ne souhaitez pas sérialiser. Rendre l'implémentation de cette méthode toujours renvoyéefalse
.Remarque: si vous aimez cette approche mais que vous ne voulez pas brouiller l'interface publique de votre classe en introduisant une
ShouldSerialize
méthode, vous pouvez utiliser unIContractResolver
pour faire la même chose par programme. Voir Sérialisation conditionnelle des propriétés dans la documentation.Approche 2: Manipuler le JSON avec JObjects
Au lieu d'utiliser
JsonConvert.SerializeObject
pour faire la sérialisation, chargez l'objet de configuration dans unJObject
, puis supprimez simplement la propriété indésirable du JSON avant de l'écrire. C'est juste quelques lignes de code supplémentaires.Approche 3: Utilisation intelligente (ab) des attributs
[JsonIgnore]
attribut à la propriété que vous ne souhaitez pas sérialiser.[JsonProperty]
attribut à l'autre setter, en lui donnant le même nom JSON que la propriété d'origine.Voici la
Config
classe révisée :la source
JsonPropertyAttribute
, à partir de C # 6.0, vous pouvez utiliser lenameof
mot - clé au lieu d'utiliser des "chaînes magiques". Cela rend la refactorisation beaucoup plus facile et infaillible - de plus, si vous oubliez de renommer des occurrences, le compilateur vous avertira de toute façon. En utilisant l'exemple de @ Brian, l'utilisation serait la suivante:[JsonProperty(nameof(ObsoleteSetting))]
Pour toute situation où il est acceptable que votre propriété de désérialisation uniquement soit marquée comme interne, il existe une solution remarquablement simple qui ne dépend pas du tout d'attributs. Marquez simplement la propriété comme interne get, mais public set:
Cela entraîne une désérialisation correcte à l'aide des paramètres par défaut / résolveurs / etc., Mais la propriété est supprimée de la sortie sérialisée.
la source
get
méthode publique ).internal
niprivate
. Il est toujours sérialisé.J'aime m'en tenir aux attributs sur celui-ci, voici la méthode que j'utilise lorsque j'ai besoin de désérialiser une propriété mais pas de la sérialiser ou vice versa.
ÉTAPE 1 - Créez l'attribut personnalisé
ÉTAPE 2 - Créer un Reslover de contrat personnalisé
ÉTAPE 3 - Ajouter un attribut où la sérialisation n'est pas nécessaire mais la désérialisation est
ÉTAPE 4 - Utilisez-le
J'espère que cela t'aides! Il convient également de noter que cela ignorera également les propriétés lorsque la désérialisation se produit, lorsque je désérialise, j'utilise simplement le convertisseur de manière conventionnelle.
la source
GetSerializableMembers
plutôt que de la remplacer entièrement?return base.GetSerializableMembers(objectType).Where(pi => !Attribute.IsDefined(pi, typeof(JsonIgnoreSerializationAttribute))).ToList();
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { ContractResolver = new JsonPropertiesResolver() }
Utilisez la propriété setter:
J'espère que cette aide.
la source
IgnoreOnSerializing
, égale à la propriété. Je recommande d'utilisernameof(IgnoreOnSerializing)
pour éviter la chaîne magique, en cas de changement de nom.Après avoir passé un temps assez long à chercher comment marquer une propriété de classe comme étant dé-sérialisable et NON sérialisable, j'ai trouvé qu'il n'y avait rien de tel pour faire cela; j'ai donc proposé une solution qui combine deux bibliothèques ou techniques de sérialisation différentes (System.Runtime.Serialization.Json & Newtonsoft.Json) et cela a fonctionné pour moi comme suit:
puis Sérialisez en utilisant "Newtonsoft.Json.JsonConvert.SerializeObject" et De-Serialize en utilisant "System.Runtime.Serialization.Json.DataContractJsonSerializer".
J'espère que cela pourra aider ...
la source
en référence à la solution de @ ThoHo, l'utilisation du setter est en fait tout ce qui est nécessaire, sans balises supplémentaires.
Pour moi, j'avais auparavant un seul identifiant de référence, que je voulais charger et ajouter à la nouvelle collection d'identifiants de référence. En modifiant la définition de l'ID de référence pour qu'elle ne contienne qu'une méthode setter, qui a ajouté la valeur à la nouvelle collection. Json ne peut pas réécrire la valeur si la propriété n'a pas de get; méthode.
Cette classe est désormais rétrocompatible avec la version précédente et enregistre uniquement les RefIds pour les nouvelles versions.
la source
Pour construire sur la réponse de Tho Ho, cela peut également être utilisé pour les champs.
la source
Selon l'endroit où cela se produit dans l'application et s'il ne s'agit que d'une seule propriété, vous pouvez le faire manuellement en définissant la valeur de la propriété sur null, puis sur le modèle, vous pouvez spécifier que la propriété soit ignorée si la valeur est nulle:
Si vous travaillez sur une application Web ASP.NET Core, vous pouvez définir globalement ceci pour toutes les propriétés de tous les modèles en définissant ceci dans votre fichier Startup.cs:
la source
Si vous utilisez JsonConvert, IgnoreDataMemberAttribute est ok. Ma bibliothèque standard ne réfrence pas Newton.Json, et j'utilise [IgnoreDataMember] pour contrôler la sérialisation des objets.
À partir du document d'aide de Newton.net .
la source
Le moyen le plus simple que j'ai trouvé à ce jour est d'inclure cette logique dans votre IContractResolver .
Exemple de code du lien ci-dessus copié ici pour la postérité:
Toutes les réponses sont bonnes, mais cette approche semble être la manière la plus claire. J'ai en fait mis en œuvre cela en recherchant un attribut sur la propriété pour SkipSerialize et SkipDeserialize afin que vous puissiez simplement marquer n'importe quelle classe que vous contrôlez. Excellente question!
la source