Garantire che le chiavi json siano minuscole in .NET


103

Esiste un modo semplice utilizzando JSON in .NET per garantire che le chiavi vengano inviate come minuscole?

Al momento sto usando la libreria Json.NET di newtonsoft e sto semplicemente usando

string loginRequest = JsonConvert.SerializeObject(auth);

In questo caso authè solo il seguente oggetto

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

Questo risulta in

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

C'è un modo per garantire che i tasti usernamee apitokenvengano visualizzati in minuscolo?

String.ToLower()Ovviamente non voglio semplicemente esaminarlo perché i valori per usernamee apitokensono maiuscoli e minuscoli.

Mi rendo conto di poterlo fare programmaticamente e creare manualmente la stringa JSON, ma ne ho bisogno per circa 20 stringhe di dati JSON e sto vedendo se riesco a risparmiare un po 'di tempo. Mi chiedo se ci siano librerie già costruite che ti consentono di applicare il minuscolo per la creazione delle chiavi.


Forse la libreria di serializzazione json offre alcuni tipi di attributi di serializzazione che potresti usare per cambiare i nomi serializzati json delle tue proprietà?
tdammers

@tdammers, grazie sto cercando di trovare qualcosa che lo faccia, ma finora senza successo. Spero che qualcuno qui possa indicarmelo.
Mark

1
Questo può essere utile nel caso in cui la tua proprietà sia composta da una parola.
Lipotam

Huh. Sto avendo il problema opposto ... inoltre - è divertente che tu abbia menzionato "Nome utente" con lettere maiuscole. Volevi dire "UserName"?
BrainSlugs83

Non semplicemente che i valori necessari per rimanere misti tra le chiavi. Solo quello che ho bisogno di toccare. Valore lasciare da solo.
Mark

Risposte:


176

Puoi creare un risolutore di contratti personalizzato per questo. Il seguente risolutore di contratti convertirà tutte le chiavi in ​​minuscolo:

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

Uso:

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

Risultato Wil in:

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

Se vuoi sempre serializzare usando il LowercaseContractResolver, considera di racchiuderlo in una classe per evitare di ripetere te stesso:

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

Che può essere usato in questo modo:

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

ASP.NET MVC4 / WebAPI

Se stai usando ASP.NET MVC4 / WebAPI, puoi usare una CamelCasePropertyNamesContractResolverlibreria da Newtonsoft.Json inclusa per impostazione predefinita.


qualche modo ragionevole per farlo al contrario? Per deserializzazione?
Shaun Rowan

1
@Anzeo Non ho provato a farlo da solo e non ho trovato alcuna informazione al riguardo nella documentazione. Una soluzione sarebbe racchiudere JsonConvert.SerializeObject nella tua classe. Vedi il mio aggiornamento.
alexn

3
Sembra, questo contractresolver personalizzato non tiene conto dell'attributo JsonProperty, se si desidera specificare eccezioni ... ad es. [JsonProperty ("alternateName")] viene ancora minuscolo o c'è un altro modo per farlo?
rekna

2
+1 per aver sottolineato il CamelCasePropertyNamesContractResolver. Ora ho trovato System.Net.Http.Formatting.JsonContractResolverl'impostazione predefinita in WebAPI e questa classe è interna. Finisco con la riscrittura JsonContractResolvercon la custodia del cammello. Qualcuno ha segnalato che questo è pubblico aspnetwebstack.codeplex.com/workitem/228
CallMeLaNN

10
CamelCasePropertyNamesContratResolvernon trasformare le proprietà in minuscolo, solo il primo carattere.
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();
    }
}

10

In Json.NET 9.0.1 e versioni successive è possibile garantire che tutti i nomi di proprietà vengano convertiti in minuscolo utilizzando un file personalizzato NamingStrategy. Questa classe estrae la logica per la rimappatura algoritmica dei nomi di proprietà dal risolutore di contratti a un oggetto separato e leggero che può essere impostato DefaultContractResolver.NamingStrategy. In questo modo si evita la necessità di creare un customContractResolver e quindi può essere più facile integrarlo in framework che hanno già i propri risolutori di contratto.

Definisci LowercaseNamingStrategycome segue:

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

Quindi serializzare come segue:

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

Appunti -


8

puoi usare "JsonProperty":

Uso:

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

0

Per me ho usato una combinazione di alcune delle altre risposte e ho finito con questo

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

era più vicino a una soluzione a ciò che stavo cercando poiché non stavo cercando di crearne uno mio

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.