c# - Bei der Serialisierung von Wörterbüchern die Umhüllung beibehalten



json.net (5)

Das ist eine sehr nette Antwort. Aber warum überschreibe nicht einfach den ResolveDictionaryKey ?

class CamelCaseExceptDictionaryResolver : CamelCasePropertyNamesContractResolver
    {
        #region Overrides of DefaultContractResolver

        protected override string ResolveDictionaryKey(string dictionaryKey)
        {
            return dictionaryKey;
        }

        #endregion
    }

Ich habe ein Web-API-Projekt wie folgt konfiguriert:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

Ich möchte jedoch, dass Wörterbuchschlüsselgehäuse unverändert bleiben. Newtonsoft.Json es ein Attribut in Newtonsoft.Json ich einer Klasse Newtonsoft.Json kann, um Newtonsoft.Json , dass die Umhüllung während der Serialisierung unverändert bleiben soll?

public class SomeViewModel
{
    public Dictionary<string, string> Data { get; set; }    
}

Hierfür gibt es kein Attribut, aber Sie können dies tun, indem Sie den Resolver anpassen.

Ich sehe, dass Sie bereits einen CamelCasePropertyNamesContractResolver . Wenn Sie eine neue Resolver-Klasse daraus ableiten und die CreateDictionaryContract() -Methode überschreiben, können Sie eine DictionaryKeyResolver Ersatzfunktion bereitstellen, die die Schlüsselnamen nicht ändert.

Hier ist der Code, den Sie benötigen würden:

class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver
{
    protected override JsonDictionaryContract CreateDictionaryContract(Type objectType)
    {
        JsonDictionaryContract contract = base.CreateDictionaryContract(objectType);

        contract.DictionaryKeyResolver = propertyName => propertyName;

        return contract;
    }
}

Demo:

class Program
{
    static void Main(string[] args)
    {
        Foo foo = new Foo
        {
            AnIntegerProperty = 42,
            HTMLString = "<html></html>",
            Dictionary = new Dictionary<string, string>
            {
                { "WHIZbang", "1" },
                { "FOO", "2" },
                { "Bar", "3" },
            }
        };

        JsonSerializerSettings settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCaseExceptDictionaryKeysResolver(),
            Formatting = Formatting.Indented
        };

        string json = JsonConvert.SerializeObject(foo, settings);
        Console.WriteLine(json);
    }
}

class Foo
{
    public int AnIntegerProperty { get; set; }
    public string HTMLString { get; set; }
    public Dictionary<string, string> Dictionary { get; set; }
}

Hier ist die Ausgabe von oben. Beachten Sie, dass alle Klasseneigenschaftsnamen Kamelgehäuse sind, aber die Wörterbuchschlüssel das ursprüngliche Gehäuse beibehalten haben.

{
  "anIntegerProperty": 42,
  "htmlString": "<html></html>",
  "dictionary": {
    "WHIZbang": "1",
    "FOO": "2",
    "Bar": "3"
  }
}

Die ausgewählte Antwort ist perfekt, aber ich schätze, wenn ich dies schreibe, muss sich der Contract Resolver in etwas ändern, weil DictionaryKeyResolver nicht mehr existiert :)

public class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver
    {
        protected override JsonDictionaryContract CreateDictionaryContract(Type objectType)
        {
            JsonDictionaryContract contract = base.CreateDictionaryContract(objectType);
            contract.PropertyNameResolver = propertyName => propertyName;
            return contract;
        }
    }

Json.NET 9.0.1 führte die NamingStrategy -Klassenhierarchie ein, um diese Art von Problem zu NamingStrategy . Sie extrahiert die Logik für die algorithmische Neuzuordnung von Eigenschaftsnamen aus dem Vertragsauflösungsdienst in eine separate, leichtgewichtige Klasse, mit der gesteuert werden kann, ob Wörterbuchschlüssel , explizit angegebene Eigenschaftsnamen und Erweiterungsdatennamen (in 10.0.1 ) neu zugeordnet werden.

Wenn Sie DefaultContractResolver und NamingStrategy auf eine Instanz von CamelCaseNamingStrategy , können Sie JSON mit Camel-Eigenschaftsnamen und unmodifizierten Wörterbuchschlüsseln generieren:

var resolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = false, OverrideSpecifiedNames = true } };
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = resolver;

Anmerkungen:

  • Die aktuelle Implementierung von CamelCasePropertyNamesContractResolver außerdem an, dass .NET-Member mit explizit angegebenen Eigenschaftsnamen (z. B. solche, in denen JsonPropertyAttribute.PropertyName festgelegt wurde) ihre Namen neu zugeordnet werden sollten:

    public CamelCasePropertyNamesContractResolver()
    {
        NamingStrategy = new CamelCaseNamingStrategy
        {
            ProcessDictionaryKeys = true,
            OverrideSpecifiedNames = true
        };
    }
    

    Der obige resolver behält dieses Verhalten bei. Wenn Sie dies nicht möchten, setzen Sie OverrideSpecifiedNames = false .

  • Json.NET hat mehrere integrierte Benennungsstrategien, einschließlich:

    1. CamelCaseNamingStrategy . Eine Kamelfallbenennungsstrategie, die die Namen-Neuzuordnungslogik enthält, die zuvor in CamelCasePropertyNamesContractResolver eingebettet war.
    2. SnakeCaseNamingStrategy . Eine Schlangenfall- Benennungsstrategie.
    3. DefaultNamingStrategy . Die Standardbenennungsstrategie. Eigenschaftsnamen und Wörterbuchschlüssel sind unverändert.

    Oder Sie können Ihre eigenen erstellen, indem Sie von der abstrakten Basisklasse NamingStrategy .

  • Es ist zwar auch möglich, die NamingStrategy einer Instanz von CamelCasePropertyNamesContractResolver zu ändern, da letztere die Vertragsinformationen global über alle Instanzen jedes Typs verteilt , kann dies zu unerwarteten Nebenwirkungen führen, wenn Ihre Anwendung versucht, mehrere Instanzen von CamelCasePropertyNamesContractResolver . Mit DefaultContractResolver existiert kein solches Problem. DefaultContractResolver ist es sicherer, es zu verwenden, wenn eine Anpassung der Casing-Logik erforderlich ist.


Wörterbücher sind spezielle Listen, wobei jeder Wert in der Liste einen Schlüssel hat, der auch eine Variable ist. Ein gutes Beispiel für ein Wörterbuch ist ein Telefonbuch.

   Dictionary<string, long> phonebook = new Dictionary<string, long>();
    phonebook.Add("Alex", 4154346543);
    phonebook["Jessica"] = 4159484588;

Beachten Sie, dass bei der Definition eines Wörterbuchs eine generische Definition mit zwei Typen bereitgestellt werden muss - dem Typ des Schlüssels und dem Typ des Werts. In diesem Fall ist der Schlüssel eine Zeichenfolge, während der Wert eine ganze Zahl ist.

Es gibt auch zwei Möglichkeiten, einen einzelnen Wert zum Wörterbuch hinzuzufügen, entweder mit dem Klammeroperator oder mit der Add-Methode.

Um zu überprüfen, ob ein Wörterbuch einen bestimmten Schlüssel enthält, können wir die Methode ContainsKey verwenden:

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

if (phonebook.ContainsKey("Alex"))
{
    Console.WriteLine("Alex's number is " + phonebook["Alex"]);
}

Um ein Element aus einem Wörterbuch zu entfernen, können Sie die Remove-Methode verwenden. Ein Element mit seinem Schlüssel aus einem Wörterbuch zu entfernen, ist schnell und sehr effizient. Wenn Sie ein Element mit seinem Wert aus einer Liste entfernen, ist der Vorgang im Gegensatz zu der Funktion zum Entfernen des Wörterbuchs langsam und ineffizient.

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

phonebook.Remove("Jessica");
Console.WriteLine(phonebook.Count);




c# json.net