c# deserialize - Eine Eigenschaft deserialisieren, aber nicht mit json.net serialisieren




jsonconverter serializeobject (7)

Es gibt tatsächlich einige ziemlich einfache Ansätze, die Sie verwenden können, um das gewünschte Ergebnis zu erzielen.

Nehmen wir zum Beispiel an, dass Ihre Klassen momentan wie folgt definiert sind:

class Config
{
    public Fizz ObsoleteSetting { get; set; }
    public Bang ReplacementSetting { get; set; }
}

enum Fizz { Alpha, Beta, Gamma }

class Bang
{
    public string Value { get; set; }
}

Und du willst das machen:

string json = @"{ ""ObsoleteSetting"" : ""Gamma"" }";

// deserialize
Config config = JsonConvert.DeserializeObject<Config>(json);

// migrate
config.ReplacementSetting = 
    new Bang { Value = config.ObsoleteSetting.ToString() };

// serialize
json = JsonConvert.SerializeObject(config);
Console.WriteLine(json);

Um das zu bekommen:

{"ReplacementSetting":{"Value":"Gamma"}}

Methode 1: Fügen Sie eine ShouldSerialize-Methode hinzu

Json.NET verfügt über die Möglichkeit, Eigenschaften seriell zu ShouldSerialize indem nach entsprechenden ShouldSerialize Methoden in der Klasse gesucht wird.

Um diese Funktion zu verwenden, fügen ShouldSerializeBlah() Ihrer Klasse eine boolesche Methode ShouldSerializeBlah() , wobei Blah durch den Namen der Eigenschaft ersetzt wird, die Sie nicht serialisieren möchten. Lassen Sie die Implementierung dieser Methode immer false .

class Config
{
    public Fizz ObsoleteSetting { get; set; }

    public Bang ReplacementSetting { get; set; }

    public bool ShouldSerializeObsoleteSetting()
    {
        return false;
    }
}

Hinweis: Wenn Ihnen dieser Ansatz gefällt, Sie jedoch die öffentliche Schnittstelle Ihrer Klasse nicht durch Einführung einer ShouldSerialize Methode ShouldSerialize , können Sie einen IContractResolver , um dasselbe programmatisch IContractResolver . Siehe Serialisierung von bedingten Eigenschaften in der Dokumentation.

Ansatz 2: Manipulieren Sie den JSON mit JObjects

Anstatt JsonConvert.SerializeObject für die Serialisierung zu verwenden, laden Sie das Konfigurationsobjekt in ein JObject , und entfernen Sie dann die unerwünschte Eigenschaft einfach aus dem JSON, bevor Sie sie JObject . Es sind nur ein paar zusätzliche Codezeilen.

JObject jo = JObject.FromObject(config);

// remove the "ObsoleteSetting" JProperty from its parent
jo["ObsoleteSetting"].Parent.Remove();

json = jo.ToString();

Ansatz 3: Kluge (ab) Verwendung von Attributen

  1. Wenden Sie ein [JsonIgnore] -Attribut auf die Eigenschaft an, die nicht serialisiert werden soll.
  2. Fügen Sie der Klasse einen alternativen privaten Eigenschaften-Setter mit demselben Typ wie der ursprünglichen Eigenschaft hinzu. Setzen Sie die Implementierung dieser Eigenschaft auf die ursprüngliche Eigenschaft.
  3. Wenden Sie ein [JsonProperty] -Attribut auf den alternativen Setter an und geben Sie ihm den gleichen JSON-Namen wie die ursprüngliche Eigenschaft.

Hier ist die überarbeitete Config Klasse:

class Config
{
    [JsonIgnore]
    public Fizz ObsoleteSetting { get; set; }

    [JsonProperty("ObsoleteSetting")]
    private Fizz ObsoleteSettingAlternateSetter
    {
        // get is intentionally omitted here
        set { ObsoleteSetting = value; }
    }

    public Bang ReplacementSetting { get; set; }
}

Wir haben einige Konfigurationsdateien, die durch das Serialisieren von C # -Objekten mit Json.net generiert wurden.

Wir möchten eine Eigenschaft der serialisierten Klasse von einer einfachen enum-Eigenschaft in eine Klasseneigenschaft migrieren.

Ein einfacher Weg, dies zu tun, wäre, die alte enum-Eigenschaft der Klasse zu belassen und dafür zu sorgen, dass Json.net diese Eigenschaft liest, wenn wir die Konfiguration laden, aber nicht, um sie beim nächsten Serialisieren des Objekts erneut zu speichern. Wir werden uns darum kümmern, die neue Klasse aus dem alten Enum separat zu generieren.

Gibt es eine einfache Möglichkeit, eine Eigenschaft eines C # -Objekts zu markieren (zB mit Attributen), so dass Json.net es NUR bei der Serialisierung ignoriert, aber beim Deserialisieren darauf achtet?


Für jede Situation, in der es akzeptabel ist, dass Ihre Deserialisierungseigenschaft intern markiert ist, gibt es eine bemerkenswert einfache Lösung, die überhaupt nicht von Attributen abhängt. Markieren Sie die Eigenschaft einfach als internal get, aber public set:

public class JsonTest {

    public string SomeProperty { internal get; set; }

}

Dies führt zu einer korrekten Deserialisierung unter Verwendung von Standardeinstellungen / Resolvern / etc. Die Eigenschaft wird jedoch von der serialisierten Ausgabe entfernt.


Setze Setzereigenschaft:

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

[JsonIgnore]
private string _ignoreOnSerializing;

[JsonIgnore]
public string IgnoreOnSerializing
{
    get { return this._ignoreOnSerializing; }
    set { this._ignoreOnSerializing = value; }
}

Ich hoffe das hilft.


Nachdem ich eine lange Zeit damit verbracht habe zu suchen, wie man eine Klasseneigenschaft als De-Serializable und NICHT als Serializable kennzeichnet, habe ich festgestellt, dass es so etwas überhaupt nicht zu tun gibt; Also kam ich auf eine Lösung, die zwei verschiedene Bibliotheken oder Serialisierungstechniken (System.Runtime.Serialization.Json & Newtonsoft.Json) kombiniert und es funktionierte für mich wie folgt:

  • Kennzeichnen Sie alle Ihre Klassen und Unterklassen als "DataContract".
  • Kennzeichnen Sie alle Eigenschaften Ihrer Klasse und Unterklassen als "DataMember".
  • Kennzeichnen Sie alle Eigenschaften Ihrer Klasse und Unterklassen als "JsonProperty" mit Ausnahme derer, die nicht serialisiert werden sollen.
  • Markieren Sie nun die Eigenschaften, die NICHT als "JsonIgnore" serialisiert werden sollen.
  • Serialisieren Sie dann mithilfe von "Newtonsoft.Json.JsonConvert.SerializeObject" und De-Serialize mithilfe von "System.Runtime.Serialization.Json.DataContractJsonSerializer".

    using System;
    using System.Collections.Generic;
    using Newtonsoft.Json;
    using System.Runtime.Serialization;
    using System.IO;
    using System.Runtime.Serialization.Json;
    using System.Text;
    
    namespace LUM_Win.model
    {
        [DataContract]
        public class User
        {
            public User() { }
            public User(String JSONObject)
            {
                MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(JSONObject));
                DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(User));
    
                User user = (User)dataContractJsonSerializer.ReadObject(stream);
                this.ID = user.ID;
                this.Country = user.Country;
                this.FirstName = user.FirstName;
                this.LastName = user.LastName;
                this.Nickname = user.Nickname;
                this.PhoneNumber = user.PhoneNumber;
                this.DisplayPicture = user.DisplayPicture;
                this.IsRegistred = user.IsRegistred;
                this.IsConfirmed = user.IsConfirmed;
                this.VerificationCode = user.VerificationCode;
                this.Meetings = user.Meetings;
            }
    
            [DataMember(Name = "_id")]
            [JsonProperty(PropertyName = "_id")]
            public String ID { get; set; }
    
            [DataMember(Name = "country")]
            [JsonProperty(PropertyName = "country")]
            public String Country { get; set; }
    
            [DataMember(Name = "firstname")]
            [JsonProperty(PropertyName = "firstname")]
            public String FirstName { get; set; }
    
            [DataMember(Name = "lastname")]
            [JsonProperty(PropertyName = "lastname")]
            public String LastName { get; set; }
    
            [DataMember(Name = "nickname")]
            [JsonProperty(PropertyName = "nickname")]
            public String Nickname { get; set; }
    
            [DataMember(Name = "number")]
            [JsonProperty(PropertyName = "number")]
            public String PhoneNumber { get; set; }
    
            [DataMember(Name = "thumbnail")]
            [JsonProperty(PropertyName = "thumbnail")]
            public String DisplayPicture { get; set; }
    
            [DataMember(Name = "registered")]
            [JsonProperty(PropertyName = "registered")]
            public bool IsRegistred { get; set; }
    
            [DataMember(Name = "confirmed")]
            [JsonProperty(PropertyName = "confirmed")]
            public bool IsConfirmed { get; set; }
    
            [JsonIgnore]
            [DataMember(Name = "verification_code")]
            public String VerificationCode { get; set; }
    
            [JsonIgnore]
            [DataMember(Name = "meeting_ids")]
            public List<Meeting> Meetings { get; set; }
    
            public String toJSONString()
            {
                return JsonConvert.SerializeObject(this, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
            }
        }
    }
    

Ich hoffe, das hilft ...


In Bezug auf die Lösung von @ ThoHo ist die Verwendung des Setter eigentlich alles, was benötigt wird, ohne zusätzliche Tags.

Für mich hatte ich vorher eine einzige Referenz-ID, die ich laden und der neuen Sammlung von Referenz-IDs hinzufügen wollte. Indem Sie die Definition der Referenz-ID so ändern, dass sie nur eine Setter-Methode enthält, die den Wert zur neuen Sammlung hinzugefügt hat. Json kann den Wert nicht zurückschreiben, wenn die Eigenschaft kein get hat; Methode.

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

Diese Klasse ist nun abwärtskompatibel zur vorherigen Version und speichert nur die RefIds für die neuen Versionen.


Um auf Tho Ho's Antwort aufzubauen, kann dies auch für Felder verwendet werden.

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

[JsonIgnore]
public string IgnoreOnSerializing;





c# json.net