दिलचस्प पोस्ट
क्या आप एक अजगर फ़ंक्शन प्राप्त करने वाले कीवर्ड तर्कों की सूची कर सकते हैं? जावा में कौन से आपरेशन परमाणु माना जाता है? स्थापित PowerShell संस्करण निर्धारित करें सी ++ 11 में आप अपना स्वयं का पाठक / लेखक लॉक कैसे लागू करेंगे? डुप्लिकेट को सूची से कैसे हटाएं? जांचें कि HTML तत्व में स्क्रॉलबार हैं या नहीं उद्देश्य सी ++ क्या है? क्या मैं ट्रैक किए गए फ़ाइलों के बाहर .git फ़ोल्डर को संग्रहीत कर सकता / सकती हूं? बिना छवि के द्विरेखित प्रक्षेप के साथ एक छवि का आकार बदलें मैटप्ललिब में आई एमशो के साथ एक विशेष रंग के रूप में मैं कैसे एनएएन वैल्यू को साजिश कर सकता हूं? फोकस प्राप्त होने पर टेक्स्टबॉक्स की सभी सामग्रियों का चयन करें (वेनिला जेएस या jQuery) रेगेक्स: प्रश्न चिह्न और बृहदान्त्र सी # का उपयोग कर स्ट्रीम से ऑडियो चलाएं ओपनसीवी में सीवीएमैट कैसे फसल कर सकता है? कैसे करने के लिए टूलटिप जोड़ने के लिए च: selectItems

Deserializing करते समय वैकल्पिक संपत्ति का नाम

इस प्रश्न के संदर्भ में:

Json.net के साथ serializing करते समय मैं संपत्ति के नाम कैसे बदल सकता हूँ?

यकीन है, महान, लेकिन क्या मैं केक रख सकता हूं और इसे खा सकता हूं?

मैं जो देख रहा हूं वह एक आंखों के अनुकूल तरीके से एक संपत्ति के लिए एक वैकल्पिक नाम इस प्रकार है कि स्ट्रिंग में या तो

कुछ इस तरह:

[BetterJsonProperty(PropertyName = "foo_bar")] public string FooBar { get; set; } 

दोनों

 { "FooBar": "yup" } 

तथा

 { "foo_bar":"uhuh" } 

अपेक्षित रूप में deserialize होगा

जैसा कि कोई विशेषता के साथ समाधान काम नहीं करेगा या जैसे वर्ग पर एक विशेषता:

  [AllowCStylePropertyNameAlternatives] 

वेब के समाधान से एकत्रित समाधान "Deserializing करते समय वैकल्पिक संपत्ति का नाम"

इसे पूरा करने का एक तरीका कस्टम JsonConverter बनाना है यह विचार है कि कनवर्टर, उन वस्तुओं के लिए जेएसओएन प्रॉपर्टी नाम की गणना करता है, जिन्हें हम रुचि रखते हैं, नामों से गैर-अल्फ़ान्यूमेरिक वर्णों को पट्टी करें और फिर उन्हें प्रतिबिंब के माध्यम से वास्तविक ऑब्जेक्ट गुणों के साथ मिलान करने का प्रयास करें। यह कैसे कोड में दिख सकता है:

 public class LaxPropertyNameMatchingConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType.IsClass; } public override bool CanWrite { get { return false; } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { object instance = objectType.GetConstructor(Type.EmptyTypes).Invoke(null); PropertyInfo[] props = objectType.GetProperties(); JObject jo = JObject.Load(reader); foreach (JProperty jp in jo.Properties()) { string name = Regex.Replace(jp.Name, "[^A-Za-z0-9]+", ""); PropertyInfo prop = props.FirstOrDefault(pi => pi.CanWrite && string.Equals(pi.Name, name, StringComparison.OrdinalIgnoreCase)); if (prop != null) prop.SetValue(instance, jp.Value.ToObject(prop.PropertyType, serializer)); } return instance; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } 

किसी विशेष वर्ग के साथ कस्टम कनवर्टर का उपयोग करने के लिए, आप उस [JsonConverter] विशेषता के साथ इस वर्ग को सजाने कर सकते हैं:

 [JsonConverter(typeof(LaxPropertyNameMatchingConverter))] public class MyClass { public string MyProperty { get; set; } public string MyOtherProperty { get; set; } } 

यहां क्रियान्वयन में कनवर्टर का एक सरल डेमो है:

 class Program { static void Main(string[] args) { string json = @" [ { ""my property"" : ""foo"", ""my-other-property"" : ""bar"", }, { ""(myProperty)"" : ""baz"", ""myOtherProperty"" : ""quux"" }, { ""MyProperty"" : ""fizz"", ""MY_OTHER_PROPERTY"" : ""bang"" } ]"; List<MyClass> list = JsonConvert.DeserializeObject<List<MyClass>>(json); foreach (MyClass mc in list) { Console.WriteLine(mc.MyProperty); Console.WriteLine(mc.MyOtherProperty); } } } 

आउटपुट:

 foo bar baz quux fizz bang 

हालांकि इस समाधान को अधिकांश मामलों में नौकरी करना चाहिए, यदि आप सीधे Json.Net स्रोत कोड को परिवर्तित करने के विचार के साथ ठीक हैं, तो एक सरल समाधान भी है। यह पता चला है कि आप Newtonsoft.Json.Serialization.JsonPropertyCollection के लिए सिर्फ एक पंक्ति कोड जोड़कर एक ही चीज़ को पूरा कर सकते हैं। Newtonsoft.Json.Serialization.JsonPropertyCollectionNewtonsoft.Json.Serialization.JsonPropertyCollectionNewtonsoft.Json.Serialization.JsonPropertyCollection क्लास। इस वर्ग में, GetClosestMatchProperty() नामक एक विधि है जो इस तरह दिखती है:

 public JsonProperty GetClosestMatchProperty(string propertyName) { JsonProperty property = GetProperty(propertyName, StringComparison.Ordinal); if (property == null) property = GetProperty(propertyName, StringComparison.OrdinalIgnoreCase); return property; } 

उस बिंदु पर जहां इस विधि को deserializer कहा जाता है, JsonPropertyCollection में deserialized जा रहा वर्ग से सभी गुण होते हैं, और propertyName पैरामीटर में JSON गुण नाम का मिलान किया जाता है। जैसा कि आप देख सकते हैं, विधि पहले एक सटीक नाम मैच की कोशिश करता है, फिर यह मामला असंवेदनशील मैच की कोशिश करता है। इसलिए हमारे पास JSON और class property names के बीच पहले से ही कई-से-एक मैपिंग हैं।

यदि आप इस पद्धति को सभी गैर-अल्फ़ान्यूमेरिक वर्णों को मिलान करने से पहले संपत्ति के नाम से बाहर निकालने के लिए संशोधित करते हैं, तो आप बिना किसी विशेष कन्वर्टर्स या विशेषताओं के ज़रिए, आपके इच्छित व्यवहार प्राप्त कर सकते हैं। यहां संशोधित कोड है:

 public JsonProperty GetClosestMatchProperty(string propertyName) { propertyName = Regex.Replace(propertyName, "[^A-Za-z0-9]+", ""); JsonProperty property = GetProperty(propertyName, StringComparison.Ordinal); if (property == null) property = GetProperty(propertyName, StringComparison.OrdinalIgnoreCase); return property; } 

बेशक, स्रोत कोड को संशोधित करने के साथ-साथ इसकी समस्याएं भी हैं, लेकिन मुझे लगा कि यह एक महत्वपूर्ण बात है।

यह पूरा करने का एक अन्य तरीका JsonReader प्रक्रिया को जल्द ही रोक रहा है, कुछ करके JsonReader और JsonWriter

 public class CustomJsonWriter : JsonTextWriter { private readonly Dictionary<string, string> _backwardMappings; public CustomJsonWriter(TextWriter writer, Dictionary<string, string> backwardMappings) : base(writer) { _backwardMappings = backwardMappings; } public override void WritePropertyName(string name) { base.WritePropertyName(_backwardMappings[name]); } } public class CustomJsonReader : JsonTextReader { private readonly Dictionary<string, string> _forwardMappings; public CustomJsonReader(TextReader reader, Dictionary<string, string> forwardMappings ) : base(reader) { _forwardMappings = forwardMappings; } public override object Value { get { if (TokenType != JsonToken.PropertyName) return base.Value; return _forwardMappings[base.Value.ToString()]; } } } 

ऐसा करने के बाद, आप करकर क्रमबद्ध कर सकते हैं

 var mappings = new Dictionary<string, string> { {"Property1", "Equivalent1"}, {"Property2", "Equivalent2"}, }; var builder = new StringBuilder(); JsonSerializer.Create().Serialize(new CustomJsonWriter(new StringWriter(builder), mappings), your_object); 

और कर के द्वारा deserialize

 var mappings = new Dictionary<string, string> { {"Equivalent1", "Property1"}, {"Equivalent2", "Property2"}, }; var txtReader = new CustomJsonReader(new StringReader(jsonString), mappings); var your_object = JsonSerializer.Create().Deserialize<Your_Type>(txtReader);