Saya memiliki proyek Web Api yang dikonfigurasi seperti ini:
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
Namun, saya ingin casing kunci kamus tetap tidak berubah. apakah ada atribut di dalam yang Newtonsoft.Json
dapat saya gunakan ke kelas untuk menunjukkan bahwa saya ingin casing tetap tidak berubah selama serialisasi?
public class SomeViewModel
{
public Dictionary<string, string> Data { get; set; }
}
Jawaban:
Tidak ada atribut untuk melakukan ini, tetapi Anda dapat melakukannya dengan menyesuaikan resolver.
Saya melihat bahwa Anda sudah menggunakan file
CamelCasePropertyNamesContractResolver
. Jika Anda mendapatkan kelas resolver baru dari itu dan menggantiCreateDictionaryContract()
metode, Anda dapat menyediakanDictionaryKeyResolver
fungsi pengganti yang tidak mengubah nama kunci.Berikut kode yang Anda perlukan:
class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver { protected override JsonDictionaryContract CreateDictionaryContract(Type objectType) { JsonDictionaryContract contract = base.CreateDictionaryContract(objectType); contract.DictionaryKeyResolver = propertyName => propertyName; return contract; } }
Demo:
class Program { static void Main(string[] args) { Foo foo = new Foo { AnIntegerProperty = 42, HTMLString = "<html></html>", Dictionary = new Dictionary<string, string> { { "WHIZbang", "1" }, { "FOO", "2" }, { "Bar", "3" }, } }; JsonSerializerSettings settings = new JsonSerializerSettings { ContractResolver = new CamelCaseExceptDictionaryKeysResolver(), Formatting = Formatting.Indented }; string json = JsonConvert.SerializeObject(foo, settings); Console.WriteLine(json); } } class Foo { public int AnIntegerProperty { get; set; } public string HTMLString { get; set; } public Dictionary<string, string> Dictionary { get; set; } }
Ini adalah keluaran dari atas. Perhatikan bahwa semua nama properti kelas menggunakan camel-cased, tetapi kunci kamus tetap menggunakan casing aslinya.
{ "anIntegerProperty": 42, "htmlString": "<html></html>", "dictionary": { "WHIZbang": "1", "FOO": "2", "Bar": "3" } }
sumber
contract.DictionaryKeyResolver = key => key;
berfungsi dengan baik.DictionaryKeyResolver
hanya saya jika properti Dictionary saya memiliki beberapa Atribut kustom?Json.NET 9.0.1 memperkenalkan
NamingStrategy
hierarki kelas untuk menangani masalah semacam ini. Ini mengekstrak logika untuk pemetaan ulang algoritmik nama properti dari resolver kontrak ke kelas ringan yang terpisah yang memungkinkan untuk mengontrol apakah kunci kamus , nama properti yang ditentukan secara eksplisit , dan nama data ekstensi (dalam 10.0.1 ) dipetakan ulang.Dengan menggunakan
DefaultContractResolver
dan menyetelNamingStrategy
ke sebuah instance,CamelCaseNamingStrategy
Anda dapat membuat JSON dengan nama properti berbasis unta dan kunci kamus yang tidak dimodifikasi dengan menyetelnya diJsonSerializerSettings.ContractResolver
:var resolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = false, OverrideSpecifiedNames = true } }; config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = resolver;
Catatan:
Implementasi saat ini
CamelCasePropertyNamesContractResolver
juga menetapkan bahwa anggota .Net dengan nama properti yang ditentukan secara eksplisit (misalnya yangJsonPropertyAttribute.PropertyName
telah ditetapkan) harus memiliki nama yang dipetakan ulang:public CamelCasePropertyNamesContractResolver() { NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = true, OverrideSpecifiedNames = true }; }
Hal di atas
resolver
mempertahankan perilaku ini. Jika Anda tidak menginginkan ini, setelOverrideSpecifiedNames = false
.Json.NET memiliki beberapa strategi penamaan bawaan termasuk:
CamelCaseNamingStrategy
. Strategi penamaan kasus unta yang berisi logika pemetaan ulang nama yang sebelumnya tertanam diCamelCasePropertyNamesContractResolver
.SnakeCaseNamingStrategy
. Sebuah kasus ular strategi penamaan.DefaultNamingStrategy
. Strategi penamaan default. Nama properti dan kunci kamus tidak berubah.Atau, Anda dapat membuatnya sendiri dengan mewarisi dari kelas dasar abstrak
NamingStrategy
.Meskipun dimungkinkan juga untuk mengubah
NamingStrategy
sebuah instanceCamelCasePropertyNamesContractResolver
, karena yang terakhir membagikan informasi kontrak secara global di semua instance dari setiap jenis , hal ini dapat menyebabkan efek samping yang tidak terduga jika aplikasi Anda mencoba menggunakan beberapa instanceCamelCasePropertyNamesContractResolver
. Tidak ada masalah seperti ituDefaultContractResolver
, jadi lebih aman digunakan saat kustomisasi logika casing diperlukan.sumber
public Dictionary<string, Dictionary<string, string>> Values { get; set; }
. Itu masih camelCase untuk kunci kamus bagian dalam.CamelCasePropertyNamesContractResolver
. Pada dasarnyaNamingStrategy
untuk yang pertama akan mempengaruhi kontrak yang dihasilkan oleh yang kedua. Itu mungkin yang Anda lihat. Coba rekomendasi baru sebagai gantinya dan beri tahu saya jika ini dapat memperbaiki masalah Anda.NamingStrategy
, sehingga mampu mengurai casing unta dan casing pascal?config
seharusnya?config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
. Sepertinya MVC 4 Web APIHttpConfiguration
, lihat Bagaimana cara menyetel JsonSerializerSettings kustom untuk Json.NET di MVC 4 Web API? .Itu jawaban yang sangat bagus. Tapi mengapa tidak mengganti saja
ResolveDictionaryKey
?class CamelCaseExceptDictionaryResolver : CamelCasePropertyNamesContractResolver { #region Overrides of DefaultContractResolver protected override string ResolveDictionaryKey(string dictionaryKey) { return dictionaryKey; } #endregion }
sumber
Jawaban yang dipilih sempurna tetapi saya kira pada saat saya mengetik ini, penyelesai kontrak harus berubah menjadi sesuatu seperti ini karena DictionaryKeyResolver tidak ada lagi :)
public class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver { protected override JsonDictionaryContract CreateDictionaryContract(Type objectType) { JsonDictionaryContract contract = base.CreateDictionaryContract(objectType); contract.PropertyNameResolver = propertyName => propertyName; return contract; } }
sumber
DictionaryKeyResolver
ditambahkan di versi 7.0.1 , danPropertyNameResolver
ditandai sebagai usang.