161 votes

Faire en sorte qu'une propriété soit désérialisée mais pas sérialisée avec json.net

Nous avons quelques fichiers de configuration qui ont été générés en sérialisant des objets C# avec Json.net.

Nous aimerions faire passer une propriété de la classe sérialisée d'une simple propriété d'enum à une propriété de classe.

Une façon 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 ne la sauvegarde pas à nouveau lors de la prochaine sérialisation de l'objet. Nous traiterons séparément la génération de la nouvelle classe à partir de l'ancienne propriété enum.

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 y prête attention lors de la désérialisation ?

3voto

OzzyTheGiant Points 309

Selon l'endroit de l'application où cela se passe et s'il s'agit d'une seule propriété, d'un seul manuel Pour ce faire, vous pouvez définir la valeur de la propriété comme nulle, puis spécifier dans le modèle que la propriété doit être ignorée si sa valeur est nulle :

[JsonProperty(NullValueHandling = NullValue.Ignore)]
public string MyProperty { get; set; }

Si vous travaillez sur une application Web ASP.NET Core, vous pouvez définir cette option de manière globale pour toutes les propriétés de tous les modèles en la définissant dans votre fichier Startup.cs :

public void ConfigureServices(IServiceCollection services) {
    // other configuration here
    services.AddMvc()
        .AddJsonOptions(options => options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore);
}

2voto

simo.379209 Points 643

En ce qui concerne la solution de @ThoHo, l'utilisation du setter est en fait tout ce qui est nécessaire, sans balises supplémentaires.

Dans mon cas, j'avais auparavant un seul ID de référence, que je voulais charger et ajouter à la nouvelle collection d'ID de référence. En modifiant la définition de la référence Id pour qu'elle ne contienne qu'une méthode setter, qui ajoute la valeur à la nouvelle collection. Json ne peut pas réécrire la valeur si la propriété n'a pas d'attribut obtenir ; méthode.

// Old property that I want to read from Json, but never write again. No getter.
public Guid RefId { set { RefIds.Add(value); } }

// New property that will be in use from now on. Both setter and getter.
public ICollection<Guid> RefIds { get; set; }

Cette classe est maintenant rétrocompatible avec la version précédente et n'enregistre que l'option RefIds pour les nouvelles versions.

2voto

Pour compléter la réponse de Tho Ho, cela peut également être utilisé pour les champs.

[JsonProperty(nameof(IgnoreOnSerializing))]
public string IgnoreOnSerializingSetter { set { IgnoreOnSerializing = value; } }

[JsonIgnore]
public string IgnoreOnSerializing;

0voto

menxin Points 540

Si vous utilisez JsonConvert, IgnoreDataMemberAttribute Ma bibliothèque standard ne fait pas référence à Newton.Json, et j'utilise [IgnoreDataMember] pour contrôler la sérialisation des objets.

De Newton.net document d'aide.

0voto

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 y prête attention lors de la désérialisation ?

La méthode la plus simple que j'ai trouvée jusqu'à présent est d'inclure cette logique dans votre IContractResolver .

Exemple de code du lien ci-dessus copié ici pour la postérité :

public class Employee
{
    public string Name { get; set; }
    public Employee Manager { get; set; }

    public bool ShouldSerializeManager()
    {
        // don't serialize the Manager property if an employee is their own manager
        return (Manager != this);
    }
}

public class ShouldSerializeContractResolver : DefaultContractResolver
{
    public new static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        if (property.DeclaringType == typeof(Employee) && property.PropertyName == "Manager")
        {
            property.ShouldSerialize =
                instance =>
                {
                    Employee e = (Employee)instance;
                    return e.Manager != e;
                };
        }

        return property;
    }
}

Toutes les réponses sont bonnes mais cette approche m'a semblé la plus propre. En fait, je l'ai implémentée en recherchant un attribut sur la propriété de SkipSerialize et SkipDeserialize, de sorte que vous pouvez simplement marquer n'importe quelle classe que vous contrôlez. Bonne question !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X