Upewnienie się, że klucze JSON są małymi literami w .NET

103

Czy istnieje prosty sposób za pomocą JSON w .NET, aby upewnić się, że klucze są wysyłane małymi literami?

W tej chwili używam biblioteki Json.NET firmy Newtonsoft i po prostu używam

string loginRequest = JsonConvert.SerializeObject(auth);

W tym przypadku authjest to tylko następujący obiekt

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

To skutkuje

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

Czy istnieje sposób, aby upewnić się, że klawisze usernamei apitokensą zapisywane małymi literami?

Oczywiście nie chcę tego po prostu przeglądać, String.ToLower()ponieważ wartości dla usernamei apitokensą mieszane.

Zdaję sobie sprawę, że mogę to zrobić programowo i ręcznie utworzyć ciąg JSON, ale potrzebuję tego na około 20 ciągów danych JSON i widzę, czy mogę zaoszczędzić trochę czasu. Zastanawiam się, czy istnieją już zbudowane biblioteki, które pozwalają wymusić małe litery przy tworzeniu kluczy.

znak
źródło
Może biblioteka serializacji json oferuje jakieś atrybuty serializacji, których można użyć do zmiany nazw zserializowanych json właściwości?
tdammers
@tdammers, dzięki, próbuję znaleźć coś, co to robi, ale jak dotąd się nie udało. Mam nadzieję, że ktoś tutaj wskaże mi to.
Mark
1
Może to być przydatne w przypadku, gdy twoje prawo składa się z jednego słowa.
Lipotam,
Huh. Mam odwrotny problem ... także - zabawne, że wspomniałeś, że „nazwa użytkownika” jest różną wielkością. Czy chodziło Ci o „UserName”?
BrainSlugs83
Nie po prostu to, że wartości potrzebne do zachowania mieszanej wielkości przypadku, tylko klawisze były tym, czego potrzebowałem. Wartość zostaw w spokoju.
Mark

Odpowiedzi:

176

Możesz w tym celu utworzyć niestandardowy mechanizm rozpoznawania umów. Następujący program do rozpoznawania kontraktu konwertuje wszystkie klucze na małe litery:

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

Stosowanie:

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

Wynik Wil w:

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

Jeśli zawsze chcesz serializować przy użyciu rozszerzenia LowercaseContractResolver, rozważ umieszczenie go w klasie, aby uniknąć powtarzania się:

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

Które można wykorzystać w ten sposób:

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

ASP.NET MVC4 / WebAPI

Jeśli używasz ASP.NET MVC4 / WebAPI, możesz użyć CamelCasePropertyNamesContractResolverbiblioteki from Newtonsoft.Json, która jest dołączona domyślnie.

alexn
źródło
jakikolwiek rozsądny sposób na odwrócenie tego? Do deserializacji?
Shaun Rowan
1
@Anzeo Sam nie próbowałem tego zrobić, aw dokumentacji nie znalazłem żadnych informacji na ten temat. Rozwiązaniem byłoby zawinięcie JsonConvert.SerializeObject we własnej klasie. Zobacz moją aktualizację.
alexn
3
Wygląda na to, że ten niestandardowy mechanizm rozwiązywania kontraktu nie bierze pod uwagę atrybutu JsonProperty, jeśli chcesz określić wyjątki ... np. [JsonProperty ("alternateName")] nadal jest pisane małymi literami, czy jest inny sposób, aby to zrobić?
rekna
2
+1 za wskazanie CamelCasePropertyNamesContractResolver. Teraz stwierdziłem, że System.Net.Http.Formatting.JsonContractResolverjest to opcja domyślna w WebAPI, a ta klasa jest wewnętrzna. Skończyło się na przepisaniu JsonContractResolverw przypadku wielbłąda. Ktoś zgłosił, że jest to publiczne aspnetwebstack.codeplex.com/workitem/228
CallMeLaNN
10
CamelCasePropertyNamesContratResolvernie przekształcaj właściwości małymi literami, tylko pierwszy znak.
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
źródło
10

W Json.NET 9.0.1 i nowszych wersjach można upewnić się, że wszystkie nazwy właściwości są konwertowane na małe litery przy użyciu niestandardowego NamingStrategy. Ta klasa wyodrębnia logikę algorytmicznego ponownego mapowania nazw właściwości z mechanizmu rozpoznawania kontraktu do oddzielnego, lekkiego obiektu, który można ustawić DefaultContractResolver.NamingStrategy. W ten sposób unika się potrzeby tworzenia niestandardowego,ContractResolver a tym samym może być łatwiejsze do zintegrowania z platformami, które mają już własne programy do rozpoznawania kontraktów.

Zdefiniuj LowercaseNamingStrategyw następujący sposób:

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

Następnie serializuj w następujący sposób:

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

Uwagi -

dbc
źródło
8

możesz użyć „JsonProperty”:

Stosowanie:

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
źródło
0

Dla mnie użyłem kombinacji niektórych innych odpowiedzi i skończyło się na tym

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

był bliżej rozwiązania tego, czego szukałem, ponieważ nie chciałem tworzyć własnego

workabyte
źródło