2017-09-28 9 views
5

जब एक नेट type में एक JSON ऑब्जेक्ट deserializing, अगर क्षेत्र के नाम से मेल नहीं खाते मैंने पाया आप संपत्तियों की एक जोड़ी के लिए [JsonProperty(PropertyName = "name")]Json.NET के साथ क्रमबद्ध करते समय सभी संपत्ति नामों को रीमेप करने के लिए सामान्य नियम कैसे लागू करें?

यह ठीक है और dandy के साथ अपने type के गुण को सजाने कर सकते हैं कि डॉन मैच नहीं है, लेकिन क्या कोई सम्मेलन या नियम स्थापित करने का कोई तरीका है?

Json

{ 
    "Job": [ 
    { 
     "Job #": "1", 
     "Job Type": "A", 
    } 
    ] 
} 

सी #

[JsonProperty(PropertyName = "Job Type")] 
    public string JobType { get; set; } 

    [JsonProperty(PropertyName = "Job #")] 
    public string JobNumber { get; set; } 

मैं इसी तरह के नाम का उपयोग कर कई क्षेत्रों है, मैं यह पता लगाने की क्या पसंद करेंगे, वहाँ एक रास्ता एक नियम स्थापित करने के लिए बताने के लिए है रिक्त स्थान को हमेशा हटाने के लिए (ईजी: Job Type -> JobType) और #Number (उदाहरण: Job # -> JobNumber) के साथ प्रतिस्थापित करें?

ऐसा लगता है कि एक कस्टम ContractResolver एकमात्र समाधान हो सकता है, लेकिन मुझे यह पता लगाना प्रतीत नहीं होता कि रिक्त स्थान निकालने और "संख्या" के साथ "#" को बदलने के लिए इसका उपयोग कैसे किया जाए। क्या किसी के पास संदर्भ उदाहरण है?

या, मुझे आशा है कि एक अच्छा सरल समाधान है जिसे मैंने अनदेखा कर दिया है।

पीएस एक बेहतर शीर्षक के लिए सुझाव भी स्वीकार करते हैं।

+1

एक शीर्षक के लिए, कैसे * Json.NET?* के साथ क्रमबद्ध करते समय सभी संपत्ति नामों को रीमेप करने के लिए सामान्य नियम कैसे लागू करें – dbc

उत्तर

2

आप यह मानते हुए Json.NET 9.0.1 साथ काम कर रहे या बाद में, इस एक कस्टम NamingStrategy के साथ किया जा सकता है।उदाहरण के लिए, यहाँ एक SnakeCaseNamingStrategy और StringUtils.ToSnakeCase() पर आधारित है जेम्स न्यूटन-राजा द्वारा:

[JsonObject(NamingStrategyType = typeof(CustomNamingStrategy))] 
public class RootObject 
{ 
    public string JobType { get; set; } 

    public string JobNumber { get; set; } 

    public int JobItemCount { get; set; } 

    public string ISOCode { get; set; } 

    public string SourceXML { get; set; } 
} 

और JSON इस प्रकार उत्पन्न हो जाएगा:

public class CustomNamingStrategy : NamingStrategy 
{ 
    public CustomNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames) 
    { 
     ProcessDictionaryKeys = processDictionaryKeys; 
     OverrideSpecifiedNames = overrideSpecifiedNames; 
    } 

    public CustomNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) 
     : this(processDictionaryKeys, overrideSpecifiedNames) 
    { 
     ProcessExtensionDataNames = processExtensionDataNames; 
    } 

    public CustomNamingStrategy() 
    { 
    } 

    protected override string ResolvePropertyName(string name) 
    { 
     return SpaceWords(name); 
    } 

    enum WordState 
    { 
     Start, 
     Lower, 
     Upper, 
     NewWord 
    } 

    static string SpaceWords(string s) 
    { 
     // Adapted from StringUtils.ToSnakeCase() 
     // https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Utilities/StringUtils.cs#L191 
     // 
     // Copyright (c) 2007 James Newton-King 
     // 
     // Permission is hereby granted, free of charge, to any person 
     // obtaining a copy of this software and associated documentation 
     // files (the "Software"), to deal in the Software without 
     // restriction, including without limitation the rights to use, 
     // copy, modify, merge, publish, distribute, sublicense, and/or sell 
     // copies of the Software, and to permit persons to whom the 
     // Software is furnished to do so, subject to the following 
     // conditions: 
     // 
     // The above copyright notice and this permission notice shall be 
     // included in all copies or substantial portions of the Software. 
     // 
     // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
     // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
     // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
     // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
     // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
     // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
     // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
     // OTHER DEALINGS IN THE SOFTWARE. 

     char wordBreakChar = ' '; 

     if (string.IsNullOrEmpty(s)) 
     { 
      return s; 
     } 

     StringBuilder sb = new StringBuilder(); 
     WordState state = WordState.Start; 

     for (int i = 0; i < s.Length; i++) 
     { 
      if (s[i] == ' ') 
      { 
       if (state != WordState.Start) 
       { 
        state = WordState.NewWord; 
       } 
      } 
      else if (char.IsUpper(s[i])) 
      { 
       switch (state) 
       { 
        case WordState.Upper: 
         bool hasNext = (i + 1 < s.Length); 
         if (i > 0 && hasNext) 
         { 
          char nextChar = s[i + 1]; 
          if (!char.IsUpper(nextChar) && nextChar != ' ') 
          { 
           sb.Append(wordBreakChar); 
          } 
         } 
         break; 
        case WordState.Lower: 
        case WordState.NewWord: 
         sb.Append(wordBreakChar); 
         break; 
       } 

       sb.Append(s[i]); 

       state = WordState.Upper; 
      } 
      else if (s[i] == wordBreakChar) 
      { 
       sb.Append(wordBreakChar); 
       state = WordState.Start; 
      } 
      else 
      { 
       if (state == WordState.NewWord) 
       { 
        sb.Append(wordBreakChar); 
       } 

       sb.Append(s[i]); 
       state = WordState.Lower; 
      } 
     } 

     sb.Replace("Number", "#"); 
     return sb.ToString(); 
    } 
} 

तो फिर तुम इस प्रकार अपने प्रकार के लिए लागू कर सकते हैं:

{ 
    "Job Type": "job type", 
    "Job #": "01010101", 
    "Job Item Count": 3, 
    "ISO Code": "ISO 9000", 
    "Source XML": "c:\temp.xml" 
} 

नोट्स:

  • यदि आप उन संपत्तियों पर लागू करने की रणनीति चाहते हैं जिनके पास पहले से ही JsonPropertyAttribute.PropertyName के माध्यम से निर्दिष्ट संपत्ति नाम हैं, तो NamingStrategy.OverrideSpecifiedNames == true सेट करें।

  • बल्कि प्रत्येक वस्तु पर यह स्थापित करने से सभी प्रकार अपनी नामकरण रणनीति लागू करने के लिए आप DefaultContractResolver.NamingStrategy में नामकरण रणनीति निर्धारित करते हैं, तो JsonSerializerSettings.ContractResolver में अनुबंध समाधानकर्ता सेट कर सकते हैं।

  • नामकरण रणनीति सी # संपत्ति नाम से जेएसओएन संपत्ति का नाम, इसके विपरीत नहीं है। इस प्रकार आपको "उन्हें बाहर निकालने" के बजाय रिक्त स्थान डालने की आवश्यकता है और "#" को "#" से प्रतिस्थापित करें। मैपिंग को तब अनुबंध समाधानकर्ता द्वारा कैश किया जाता है और एक रिवर्स लुकअप deserialization के दौरान किया जाता है।

1

हां ContractResolver जाने का रास्ता है।

समस्या यह है कि ये केवल गंतव्य संपत्ति से स्रोत तक जाने के लिए प्रतीत होता है, यानी "JobType" -> "Job Type", जैसा कि आप चाहें उतना नहीं। यह समाधान को आप चाहते हैं की तुलना में थोड़ा अधिक flaky बनाता है।

सबसे पहले हम अपने ContractResolver बनाने, DefaultContractResolver से इनहेरिट, तो यह अलग सा से सामान्य रूप से सभी काम करता है हम अनुकूलित करने के लिए करना चाहते हैं:

public class JobContractResolver : DefaultContractResolver 
{ 
    protected override string ResolvePropertyName(string propertyName) 
    { 
     // first replace all capital letters with space then letter ("A" => " A"). This might include the first letter, so trim the result. 
     string result = Regex.Replace(propertyName, "[A-Z]", x => " " + x.Value).Trim(); 

     // now replace Number with a hash 
     result = result.Replace("Number", "#"); 

     return result; 
    } 
} 
हमारे अक्रमांकन में

फिर, हम JsonSerializerSettings में ContractResolver सेट:

static void Main(string[] args) 
{ 
    string input = @"{""Job #"": ""1"", ""Job Type"": ""A""}"; 

    var job1 = JsonConvert.DeserializeObject<Job1>(input, new JsonSerializerSettings 
    { 
     ContractResolver = new JobContractResolver() 
    }); 

    Console.WriteLine("JobType: {0}", job1.JobType); 
    Console.WriteLine("JobNumber: {0}", job1.JobNumber); 
} 
संबंधित मुद्दे

 संबंधित मुद्दे