Sicherstellen, dass JSON-Schlüssel in .NET in Kleinbuchstaben geschrieben sind

103

Gibt es eine einfache Möglichkeit, JSON in .NET zu verwenden, um sicherzustellen, dass die Schlüssel in Kleinbuchstaben gesendet werden?

Im Moment benutze ich die Json.NET-Bibliothek von newtonsoft und benutze sie einfach

string loginRequest = JsonConvert.SerializeObject(auth);

In diesem Fall authhandelt es sich nur um das folgende Objekt

public class Authority
{
    public string Username { get; set; }
    public string ApiToken { get; set; }
}

Das führt zu

{"Username":"Mark","ApiToken":"xyzABC1234"}

Gibt es eine Möglichkeit , um sicherzustellen , dass die usernameund apitokenTasten als Klein kommen durch?

Ich möchte es String.ToLower()natürlich nicht einfach durchgehen, weil die Werte für usernameund apitokengemischt sind.

Mir ist klar, dass ich dies programmgesteuert tun und die JSON-Zeichenfolge manuell erstellen kann, aber ich benötige dies für ungefähr 20 JSON-Datenzeichenfolgen, und ich sehe, ob ich mir etwas Zeit sparen kann. Ich frage mich, ob es bereits erstellte Bibliotheken gibt, mit denen Sie Kleinbuchstaben für die Schlüsselerstellung erzwingen können.

Kennzeichen
quelle
Vielleicht bietet die json-Serialisierungsbibliothek eine Art Serialisierungsattribute, mit denen Sie die json-serialisierten Namen Ihrer Eigenschaften ändern können?
tdammers
@tdammers, danke, ich versuche etwas zu finden, das das tut, aber bisher erfolglos. Ich hoffe, jemand hier könnte mich darauf hinweisen.
Mark
1
Dies kann nützlich sein, wenn Ihre Eigenschaft aus einem Wort besteht.
Lipotam
Huh. Ich habe das gegenteilige Problem ... auch - es ist lustig, dass Sie erwähnen, dass "Benutzername" ein gemischter Fall ist. Meinten Sie "UserName"?
BrainSlugs83
Nein, einfach, dass die Werte gemischt bleiben mussten, wenn die Tasten Nur das waren, was ich berühren musste. Wert in Ruhe lassen.
Mark

Antworten:

176

Hierfür können Sie einen benutzerdefinierten Vertragsauflöser erstellen. Der folgende Vertragsauflöser konvertiert alle Schlüssel in Kleinbuchstaben:

public class LowercaseContractResolver : DefaultContractResolver
{
    protected override string ResolvePropertyName(string propertyName)
    {
        return propertyName.ToLower();
    }
}

Verwendung:

var settings = new JsonSerializerSettings();
settings.ContractResolver = new LowercaseContractResolver();
var json = JsonConvert.SerializeObject(authority, Formatting.Indented, settings);

Wil Ergebnis in:

{"username":"Mark","apitoken":"xyzABC1234"}

Wenn Sie immer mit serialisieren möchten, sollten Sie LowercaseContractResolveres in eine Klasse einschließen, um zu vermeiden, dass Sie sich wiederholen:

public class LowercaseJsonSerializer
{
    private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        ContractResolver = new LowercaseContractResolver()
    };

    public static string SerializeObject(object o)
    {
        return JsonConvert.SerializeObject(o, Formatting.Indented, Settings);
    }

    public class LowercaseContractResolver : DefaultContractResolver
    {
        protected override string ResolvePropertyName(string propertyName)
        {
            return propertyName.ToLower();
        }
    }
}

Welches kann so verwendet werden:

var json = LowercaseJsonSerializer.SerializeObject(new { Foo = "bar" });
// { "foo": "bar" }

ASP.NET MVC4 / WebAPI

Wenn Sie ASP.NET MVC4 / WebAPI verwenden, können Sie eine CamelCasePropertyNamesContractResolverBibliothek von Newtonsoft.Json verwenden, die standardmäßig enthalten ist.

alexn
quelle
Gibt es einen vernünftigen Weg, dies umgekehrt zu tun? Zur Deserialisierung?
Shaun Rowan
1
@Anzeo Ich habe nicht versucht, das selbst zu tun, und ich habe keine Informationen dazu in der Dokumentation gefunden. Eine Lösung wäre, JsonConvert.SerializeObject in Ihre eigene Klasse einzuschließen. Siehe mein Update.
Alexn
3
Es scheint, dass dieser benutzerdefinierte Vertragslöser das JsonProperty-Attribut nicht berücksichtigt, wenn Sie Ausnahmen angeben möchten ... z.
rekna
2
+1 für den Hinweis auf die CamelCasePropertyNamesContractResolver. Jetzt habe ich festgestellt, dass dies System.Net.Http.Formatting.JsonContractResolverdie Standardeinstellung in WebAPI ist und diese Klasse intern ist. Am Ende schreibe ich mit Kameletui um JsonContractResolver. Jemand hat berichtet, dass dies öffentlich ist. Aspnetwebstack.codeplex.com/workitem/228
CallMeLaNN
10
CamelCasePropertyNamesContratResolverTransformieren Sie die Eigenschaften nicht in Kleinbuchstaben, sondern nur in das erste Zeichen.
ToXinE
23
protected void Application_Start() {
    JsonConfig.Configure();   
}

public static class JsonConfig
{
    public static void Configure(){
        var formatters = GlobalConfiguration.Configuration.Formatters;
        var jsonFormatter = formatters.JsonFormatter;
        var settings = jsonFormatter.SerializerSettings;

        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }
}
Sagi
quelle
10

In Json.NET 9.0.1 und höher kann mithilfe einer benutzerdefinierten Funktion sichergestellt werden, dass alle Eigenschaftsnamen in Kleinbuchstaben konvertiert werden NamingStrategy. Diese Klasse extrahiert die Logik für die algorithmische Neuzuordnung von Eigenschaftsnamen aus dem Vertragsauflöser zu einem separaten, leichtgewichtigen Objekt, das festgelegt werden kann DefaultContractResolver.NamingStrategy. Dadurch wird die Notwendigkeit vermieden, eine benutzerdefinierteContractResolver Version zu erstellen, und es kann daher einfacher sein, diese in Frameworks zu integrieren, die bereits über eigene Vertragsauflöser verfügen.

Definieren Sie LowercaseNamingStrategywie folgt:

public class LowercaseNamingStrategy : NamingStrategy
{
    protected override string ResolvePropertyName(string name)
    {
        return name.ToLowerInvariant();
    }
}

Dann serialisieren Sie wie folgt:

var settings = new JsonSerializerSettings
{
    ContractResolver = new DefaultContractResolver { NamingStrategy = new LowercaseNamingStrategy() },
};
string loginRequest = JsonConvert.SerializeObject(auth, settings);

Anmerkungen -

dbc
quelle
8

Sie können "JsonProperty" verwenden:

Verwendung:

public class Authority
{
    [JsonProperty("userName")] // or [JsonProperty("username")]
    public string Username { get; set; }
    [JsonProperty("apiToken")] // or [JsonProperty("apitoken")]
    public string ApiToken { get; set; }
}

var json  = JsonConvert.SerializeObject(authority);
Jorgelig
quelle
0

Für mich habe ich eine Kombination aus einigen der anderen Antworten verwendet und am Ende diese erhalten

        return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });

war näher an einer Lösung für das, was ich suchte, da ich nicht meine eigene erstellen wollte

Workabyte
quelle