S'assurer que les clés Json sont en minuscules dans .NET

103

Existe-t-il un moyen simple d'utiliser JSON dans .NET pour s'assurer que les clés sont envoyées en minuscules?

En ce moment, j'utilise la bibliothèque Json.NET de newtonsoft et j'utilise simplement

string loginRequest = JsonConvert.SerializeObject(auth);

Dans ce cas authest juste l'objet suivant

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

Cela se traduit par

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

Existe-t-il un moyen de garantir que les touches usernameet apitokenapparaissent en minuscules?

Je ne veux pas simplement l'exécuter, String.ToLower()bien sûr, car les valeurs de usernameet apitokensont mixtes.

Je me rends compte que je peux le faire par programme et créer la chaîne JSON manuellement, mais j'en ai besoin pour environ 20 chaînes de données JSON et je vois si je peux gagner du temps. Je me demande s'il existe des bibliothèques déjà construites qui vous permettent d'appliquer des minuscules pour la création de clés.

marque
la source
Peut-être que la bibliothèque de sérialisation json offre une sorte d'attributs de sérialisation que vous pourriez utiliser pour changer les noms sérialisés json de vos propriétés?
tdammers
@tdammers, merci, j'essaie de trouver quelque chose qui fait ça, mais sans succès jusqu'à présent. En espérant que quelqu'un ici puisse m'indiquer cela.
Marquez le
1
Cela peut être utile dans le cas où votre propriété se compose d'un seul mot.
Lipotam
Huh. J'ai le problème inverse ... aussi - c'est drôle que vous mentionniez que "Nom d'utilisateur" est un cas mixte. Voulez-vous dire "UserName"?
BrainSlugs83
Non simplement que les valeurs devaient rester mixtes cas les touches Seules étaient ce que j'ai besoin de toucher. Valeur laisser tranquille.
Mark

Réponses:

176

Vous pouvez créer un résolveur de contrat personnalisé pour cela. Le résolveur de contrat suivant convertira toutes les clés en minuscules:

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

Usage:

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

Wil se traduit par:

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

Si vous souhaitez toujours sérialiser à l'aide de LowercaseContractResolver, envisagez de l'encapsuler dans une classe pour éviter de vous répéter:

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();
        }
    }
}

Qui peut être utilisé comme ceci:

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

ASP.NET MVC4 / WebAPI

Si vous utilisez ASP.NET MVC4 / WebAPI, vous pouvez utiliser une CamelCasePropertyNamesContractResolverbibliothèque de Newtonsoft.Json incluse par défaut.

Alexn
la source
un moyen raisonnable de faire cela en sens inverse? Pour la désérialisation?
Shaun Rowan
1
@Anzeo Je n'ai pas essayé de le faire moi-même et je n'ai trouvé aucune information à ce sujet dans la documentation. Une solution consisterait à envelopper JsonConvert.SerializeObject dans votre propre classe. Voir ma mise à jour.
alexn
3
Il semble que ce résolveur de contrat personnalisé ne prend pas en compte l'attribut JsonProperty, si vous souhaitez spécifier des exceptions ... par exemple [JsonProperty ("anotherName")] est toujours en minuscules ou y a-t-il une autre façon de le faire?
rekna le
2
+1 pour avoir signalé le CamelCasePropertyNamesContractResolver. Maintenant, j'ai trouvé System.Net.Http.Formatting.JsonContractResolverla valeur par défaut dans WebAPI et cette classe est interne. Je finis par réécrire JsonContractResolveravec un étui camel. Quelqu'un a signalé que c'était public aspnetwebstack.codeplex.com/workitem/228
CallMeLaNN
10
CamelCasePropertyNamesContratResolverne transformez pas les propriétés en minuscules, juste le premier caractère.
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
la source
10

Dans Json.NET 9.0.1 et versions ultérieures, il est possible de garantir que tous les noms de propriété sont convertis en minuscules à l'aide d'un fichier NamingStrategy. Cette classe extrait la logique du remappage algorithmique des noms de propriété du résolveur de contrat vers un objet léger et distinct qui peut être défini DefaultContractResolver.NamingStrategy. Cela évite d'avoir à créer une coutumeContractResolver et peut donc être plus facile à intégrer dans des frameworks qui ont déjà leurs propres résolveurs de contrat.

Définissez LowercaseNamingStrategycomme suit:

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

Puis sérialisez comme suit:

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

Remarques -

dbc
la source
8

vous pouvez utiliser "JsonProperty":

Usage:

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
la source
0

Pour moi, j'ai utilisé une combinaison de certaines des autres réponses et j'ai fini avec ceci

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

était plus proche d'une solution à ce que je cherchais car je ne cherchais pas à créer la mienne

workabyte
la source