Asegurarse de que las claves json estén en minúsculas en .NET

103

¿Existe una forma sencilla de usar JSON en .NET para garantizar que las claves se envíen en minúsculas?

En este momento estoy usando la biblioteca Json.NET de newtonsoft y simplemente estoy usando

string loginRequest = JsonConvert.SerializeObject(auth);

En este caso authes solo el siguiente objeto

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

Esto resulta en

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

¿Hay alguna forma de garantizar que las teclas usernamey apitokenaparezcan en minúsculas?

No quiero simplemente ejecutarlo, por String.ToLower()supuesto, porque los valores de usernamey apitokenson mayúsculas y minúsculas.

Me doy cuenta de que puedo hacer esto programáticamente y crear la cadena JSON manualmente, pero necesito esto para aproximadamente 20 cadenas de datos JSON y estoy viendo si puedo ahorrarme algo de tiempo. Me pregunto si hay alguna biblioteca ya construida que le permita aplicar minúsculas para la creación de claves.

marca
fuente
¿Quizás la biblioteca de serialización json ofrece algún tipo de atributos de serialización que podría usar para cambiar los nombres serializados de json de sus propiedades?
tdammers
@tdammers, gracias. Estoy tratando de encontrar algo que haga eso, pero hasta ahora no ha tenido éxito. Esperando que alguien aquí me lo indique.
Mark
1
Esto puede ser útil en caso de que su propiedad se componga de una palabra.
Lipotam
¿Eh? Tengo el problema opuesto ... también, es gracioso que menciones que "Nombre de usuario" es una combinación de mayúsculas y minúsculas. ¿Quiso decir "UserName"?
BrainSlugs83
No, simplemente, los valores debían permanecer mixtos en caso de que las teclas solo fueran lo que necesitaba tocar. Valor dejar en paz.
Mark

Respuestas:

176

Puede crear un solucionador de contratos personalizado para esto. El siguiente solucionador de contratos convertirá todas las claves a minúsculas:

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

Wil resultado en:

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

Si siempre desea serializar usando el LowercaseContractResolver, considere envolverlo en una clase para evitar repetirse:

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

Que se puede utilizar así:

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

ASP.NET MVC4 / WebAPI

Si está utilizando ASP.NET MVC4 / WebAPI, puede utilizar una CamelCasePropertyNamesContractResolverbiblioteca de Newtonsoft.Json que se incluye de forma predeterminada.

alexn
fuente
alguna forma razonable de hacer esto a la inversa? ¿Para deserialización?
Shaun Rowan
1
@Anzeo No he intentado hacer eso yo mismo, y no encontré ninguna información al respecto en la documentación. Una solución sería envolver JsonConvert.SerializeObject en su propia clase. Ver mi actualización.
alexn
3
Parece que este solucionador de contratos personalizado no tiene en cuenta el atributo JsonProperty, si desea especificar excepciones ... por ejemplo, [JsonProperty ("alternateName")] todavía se pone en minúsculas o hay otra forma de hacerlo?
rekna
2
+1 por señalar el CamelCasePropertyNamesContractResolver. Ahora encontré que System.Net.Http.Formatting.JsonContractResolveres el predeterminado en WebAPI y esta clase es interna. Termino reescribiendo JsonContractResolvercon caja camel. Alguien informó que esto era público aspnetwebstack.codeplex.com/workitem/228
CallMeLaNN
10
CamelCasePropertyNamesContratResolverno transforme las propiedades en minúsculas, solo el primer carácter.
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
fuente
10

En Json.NET 9.0.1 y versiones posteriores, es posible asegurarse de que todos los nombres de propiedad se conviertan a minúsculas mediante el uso de un archivo NamingStrategy. Esta clase extrae la lógica para la reasignación algorítmica de los nombres de propiedad del solucionador de contratos a un objeto ligero separado en el que se puede configurar DefaultContractResolver.NamingStrategy. Al hacerlo, se evita la necesidad de crear una costumbreContractResolver y, por lo tanto, puede ser más fácil de integrar en marcos que ya tienen sus propios resolutores de contratos.

Defina LowercaseNamingStrategycomo sigue:

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

Luego serialice de la siguiente manera:

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

Notas -

dbc
fuente
8

puede utilizar "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);
Jorgelig
fuente
0

Para mí, utilicé una combinación de algunas de las otras respuestas y terminé con esta

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

estaba más cerca de una solución a lo que estaba buscando, ya que no estaba buscando crear mi propio

workabyte
fuente