Memastikan kunci json menggunakan huruf kecil di .NET

103

Apakah ada cara sederhana menggunakan JSON di .NET untuk memastikan bahwa kunci dikirim dengan huruf kecil?

Saat ini saya menggunakan perpustakaan Json.NET newtonsoft dan hanya menggunakan

string loginRequest = JsonConvert.SerializeObject(auth);

Dalam hal authini hanya objek berikut

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

Ini menghasilkan

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

Apakah ada cara untuk memastikan bahwa kunci usernamedan apitokenmuncul sebagai huruf kecil?

Saya tidak ingin hanya menjalankannya String.ToLower()saja karena nilai untuk usernamedan apitokenkasus campuran.

Saya menyadari bahwa saya dapat melakukan ini secara terprogram dan membuat string JSON secara manual, tetapi saya membutuhkan ini untuk kira-kira 20 atau lebih string data JSON dan saya melihat apakah saya dapat menghemat waktu. Saya bertanya-tanya apakah sudah ada pustaka yang dibangun yang memungkinkan Anda menerapkan huruf kecil untuk pembuatan kunci.

Menandai
sumber
Mungkin lib serialisasi json menawarkan beberapa jenis atribut serialisasi yang dapat Anda gunakan untuk mengubah nama serialisasi json pada properti Anda?
tdammers
@tdammers, terima kasih saya mencoba menemukan sesuatu yang dapat melakukannya, tetapi sejauh ini tidak berhasil. Berharap seseorang di sini bisa menunjukkannya padaku.
Tandai
1
Ini dapat berguna jika properti Anda terdiri dari satu kata.
Lipotam
Hah. Saya mengalami masalah sebaliknya ... juga - lucu bahwa Anda menyebutkan "Nama pengguna" dalam huruf yang berbeda-beda. Apakah maksud Anda "UserName"?
BrainSlugs83
Tidak hanya bahwa nilai-nilai yang diperlukan untuk tetap menggunakan huruf besar-kecil, kunci-kuncinya Hanya apa yang perlu saya sentuh. Nilai biarkan saja.
Tandai

Jawaban:

176

Anda dapat membuat pemecah kontrak kustom untuk ini. Penyelesai kontrak berikut akan mengonversi semua kunci menjadi huruf kecil:

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

Pemakaian:

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

Wil menghasilkan:

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

Jika Anda selalu ingin membuat serial menggunakan LowercaseContractResolver, pertimbangkan untuk menggabungkannya di kelas untuk menghindari pengulangan:

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

Yang bisa digunakan seperti ini:

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

ASP.NET MVC4 / WebAPI

Jika Anda menggunakan ASP.NET MVC4 / WebAPI, Anda dapat menggunakan CamelCasePropertyNamesContractResolverpustaka dari Newtonsoft.Json yang disertakan secara default.

alexn
sumber
ada cara yang masuk akal untuk melakukan ini secara terbalik? Untuk deserialization?
Shaun Rowan
1
@Anzeo Saya belum mencoba melakukannya sendiri, dan saya tidak menemukan informasi apa pun tentang itu di dokumentasi. Solusinya adalah membungkus JsonConvert.SerializeObject di kelas Anda sendiri. Lihat pembaruan saya.
alexn
3
Tampaknya, pemecah kontrak kustom ini tidak memperhitungkan atribut JsonProperty, jika Anda ingin menetapkan pengecualian ... misalnya [JsonProperty ("alternateName")] masih menggunakan huruf kecil atau apakah ada cara lain untuk melakukannya?
rekna
2
1 untuk menunjukkan CamelCasePropertyNamesContractResolver. Sekarang saya menemukan System.Net.Http.Formatting.JsonContractResolveradalah default di WebAPI dan kelas ini bersifat internal. Saya berakhir dengan menulis ulang JsonContractResolverdengan kasus unta. Seseorang melaporkan ini sebagai publik aspnetwebstack.codeplex.com/workitem/228
CallMeLaNN
10
CamelCasePropertyNamesContratResolverjangan mengubah properti menjadi huruf kecil, cukup karakter pertama.
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
sumber
10

Di Json.NET 9.0.1 dan yang lebih baru, dimungkinkan untuk memastikan bahwa semua nama properti diubah menjadi huruf kecil dengan menggunakan kustom NamingStrategy. Kelas ini mengekstrak logika untuk pemetaan ulang algoritmik nama properti dari resolver kontrak ke objek ringan yang terpisah yang dapat disetel DefaultContractResolver.NamingStrategy. Melakukan hal itu menghindari kebutuhan untuk membuat kebiasaanContractResolver dan dengan demikian mungkin lebih mudah diintegrasikan ke dalam kerangka kerja yang sudah memiliki penyelesai kontrak sendiri.

Definisikan LowercaseNamingStrategysebagai berikut:

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

Kemudian buat serial sebagai berikut:

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

Catatan -

dbc
sumber
8

Anda dapat menggunakan "JsonProperty":

Pemakaian:

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
sumber
0

Bagi saya, saya menggunakan kombinasi dari beberapa jawaban lain dan berakhir dengan ini

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

lebih dekat ke solusi untuk apa yang saya cari karena saya tidak ingin membuatnya sendiri

workabyte
sumber