2016-06-29 19 views
6

में परिभाषित करने के लिए json स्ट्रिंग और नक्शा गुण को क्रमानुसार मैं निम्नलिखित JSON स्ट्रिंग है:Json.NET deserialize या अलग संपत्ति के नाम क्रम

public class Details 
{ 
    public string property1 { get; set; } 
    public string property2 { get; set; } 
    public string property3 { get; set; } 
    public int property4 { get; set; } 
} 

public class Values 
{ 
    public Details details { get; set; } 
    public int count { get; set; } 
} 

public class RootObject 
{ 
    public Values values { get; set; } 
} 
:

{ 
    "values": { 
     "details": { 
      "property1": "94", 
      "property2": "47", 
      "property3": "32", 
      "property4": 1 
     }, 
     count: 4 
    } 
}  

मैं निम्नलिखित मॉडल के लिए इस मैप करने के लिए जा रहा हूँ

JsonConvert.DeserializeObject<RootObject>(jsonString); 
:

मैं जब इस तरह इस JSON स्ट्रिंग deserializing कार्यावधि में अलग-अलग नामों के लिए इन संपत्ति के नाम मैप करने के लिए सक्षम होना चाहते हैं

उदाहरण के लिए, deserialization प्रक्रिया में, मैं "property1" का नाम "differen_property_name1" या "differen_property_name2" या "differen_property_name3" को deserialize करना चाहता हूँ। क्योंकि मैं क्रम में नए नाम का चयन कर रहा हूँ (नया नाम जो मैं करने के लिए "property1" नाम बदलने के लिए होगा), मैं, समाधान JsonPropertyAttribute का उपयोग कर उपयोग नहीं कर सकते, जैसा कि यहाँ का सुझाव दिया:

.NET NewtonSoft JSON deserialize map to a different property name

उपर्युक्त प्रश्न (जैक का उत्तर) के उत्तरों में से एक डिफ़ॉल्ट कंट्रैक्ट रिसेल्वर की विरासत का उपयोग करता है लेकिन यह उस मामले में काम नहीं कर रहा है।

अद्यतन

बाद में, मैं वस्तु मैं अक्रमांकन से मिला क्रमानुसार और विभिन्न संपत्ति के नाम, क्रम में परिभाषित करने के लिए गुण मैप करने के लिए की जरूरत है। मैं एक ही विधि का इस्तेमाल किया के रूप में ब्रायन क्रमबद्धता करने के लिए प्रस्तावित:

मैं अपने नए संपत्ति के नाम को मैप करने के शब्दकोश का प्रयोग किया:

var map = new Dictionary<Type, Dictionary<string, string>> 
{ 
    { 
     typeof(Details), 
     new Dictionary<string, string> 
     { 
      {"property1", "myNewPropertyName1"}, 
      {"property2", "myNewPropertyName2"}, 
      {"property3", "myNewPropertyName3"}, 
      {"property4", "myNewPropertyName4"} 
     } 
    } 
};  

और फिर मैं ब्रायन की DynamicMappingResolver इस्तेमाल किया इस तरह वस्तु को क्रमानुसार करने:

var settings = new JsonSerializerSettings 
{ 
    ContractResolver = new DynamicMappingResolver(map) 
}; 

var root = JsonConvert.SerializeObject(myObjectInstance, settings);    
+0

क्योंकि मैं क्रम जो नया नाम मैं संपत्ति के लिए और JsonPropertyAttribute साथ आप एक "हार्ड कोडित" नाम का उपयोग करना देना चाहता हूँ में तय करना चाहते हैं। –

+0

एक तरीका (हालांकि यह बदसूरत हो सकता है) पहले JSON को deserialize करना होगा, और फिर नए नामों के साथ वस्तु को deserialized वस्तु मानचित्र। हालांकि, एक और अधिक सुरुचिपूर्ण तरीका हो सकता है। – Tim

+0

@Tim, नए नामों के साथ किसी ऑब्जेक्ट पर deserialized ऑब्जेक्ट को कैसे मैप किया जाएगा जब नए नाम रनटाइम पर परिभाषित किए जाने की आवश्यकता है? –

उत्तर

5

ऐसा करने के लिए आप एक कस्टम ContractResolver का उपयोग कर सकते हैं। असल में यह एक ही विचार है कि [JsonProperty] प्रत्येक वर्ग सदस्य पर विशेषता है जिसके लिए आप किसी भिन्न JSON प्रॉपर्टी नाम पर मैप करना चाहते हैं, सिवाय इसके कि आप इसे रिजॉल्वर के माध्यम से प्रोग्रामेटिक रूप से करते हैं। जब आप deserializing से पहले इसे स्थापित करते हैं तो आप अपने वांछित मैपिंग्स का एक शब्दकोश रिज़ॉल्वर को पास कर सकते हैं।

class DynamicMappingResolver : DefaultContractResolver 
{ 
    private Dictionary<Type, Dictionary<string, string>> memberNameToJsonNameMap; 

    public DynamicMappingResolver(Dictionary<Type, Dictionary<string, string>> memberNameToJsonNameMap) 
    { 
     this.memberNameToJsonNameMap = memberNameToJsonNameMap; 
    } 

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty prop = base.CreateProperty(member, memberSerialization); 
     Dictionary<string, string> dict; 
     string jsonName; 
     if (memberNameToJsonNameMap.TryGetValue(member.DeclaringType, out dict) && 
      dict.TryGetValue(member.Name, out jsonName)) 
     { 
      prop.PropertyName = jsonName; 
     } 
     return prop; 
    } 
} 

अपने मैपिंग युक्त समाधानकर्ता का उपयोग करने के पहले का निर्माण एक Dictionary<Type, Dictionary<string, string>>:

यहां कस्टम समाधानकर्ता कोड कैसा दिखाई दे सकता है। बाहरी शब्दकोश की कुंजी वह वर्ग प्रकार है जिसका गुण आप मानचित्र बनाना चाहते हैं; आंतरिक शब्दकोश क्लास संपत्ति नामों का JSON संपत्ति नामों का मैपिंग है। आपको केवल उन गुणों के लिए मैपिंग प्रदान करने की आवश्यकता है जिनके नाम JSON से पहले से मेल नहीं खाते हैं।

तो, उदाहरण के लिए, यदि आपके JSON इस तरह देखा (details ऑब्जेक्ट के अंदर गुणों की बदली हुई नाम नोटिस) ...

{ 
    "values": { 
     "details": { 
      "foo": "94", 
      "bar": "47", 
      "baz": "32", 
      "quux": 1 
     }, 
     count: 4 
    } 
} 

... और आप वर्गों के लिए यह मैप करने के लिए करना चाहता था

var map = new Dictionary<Type, Dictionary<string, string>> 
{ 
    { 
     typeof(Details), 
     new Dictionary<string, string> 
     { 
      {"property1", "foo"}, 
      {"property2", "bar"}, 
      {"property3", "baz"}, 
      {"property4", "quux"} 
     } 
    } 
}; 

अंतिम चरण अप करने के लिए सेटिंग्स एक नया समाधानकर्ता उदाहरण के साथ serializer सेटिंग्स निर्धारित करने की है, यह मानचित्रण शब्दकोश तुम सिर्फ निर्माण दे, और उसके बाद से पारित है: अपने सवाल में, अगर आप इस तरह शब्दकोश बनाना होगा JsonConvert.DeserializeObject()https://dotnetfiddle.net/ULkB0J

+0

बिल्कुल वही जो मैं खोज रहा था। धन्यवाद!! –

0

मुझे विश्वास नहीं है कि JSON.net के लिए आप जो भी खोज रहे हैं उसके लिए कोई समर्थन है। यदि आप ऐसा करते हैं तो आपको JSON को JObject में deserialize करना चाहिए यदि आप प्रारूप या कुछ सामान्य एक नहीं जानते हैं (उदाहरण के लिए यदि JSON हमेशा property1 कहता है तो आप इसका प्रतिनिधित्व करने के लिए एक सामान्य वस्तु का उपयोग कर सकते हैं)।

एक बार जब आपका सामान्य ऑब्जेक्ट हो जाए तो आपको फ़ील्ड का अनुवाद करने की आवश्यकता होगी। कोई भी जो परिवर्तनीय नहीं है सीधे किया जा सकता है, लेकिन किसी और चीज के लिए आपको प्रतिबिंब का उपयोग करने की आवश्यकता होगी।

असल में इसमें प्रकार (typeof(Details) या obj.GetType()) प्राप्त करना शामिल है और फिर उस संपत्ति की खोज करना है जिसे आप अपडेट करना चाहते हैं। अंत में आप सेटर विधि को ढूंढने में सक्षम होना चाहिए और इसे अपने सामान्य ऑब्जेक्ट से मूल मान की आपूर्ति करना चाहिए।

1

क्यों एक कदम में ऐसा करते हैं:

var settings = new JsonSerializerSettings 
{ 
    ContractResolver = new DynamicMappingResolver(map) 
}; 

var root = JsonConvert.DeserializeObject<RootObject>(json, settings); 

यहाँ एक डेमो है? अपने मानक ऑब्जेक्ट में deserialize क्यों नहीं है और फिर Automapper का उपयोग कर गतिशील रूप से उन्हें मानचित्रित करें?

कुछ की तरह:

Mapper.Initialize(c => 
{ 
    c.ReplaceMemberName("property1 ", "differen_property_name1"); 
}); 
संबंधित मुद्दे