2016-03-08 7 views
5

JSON इस तरह दिखता है:से बचें एक अंकीय संपत्ति को JSON स्ट्रिंग टोकन deserializing

{ 
    "x": "50" 
} 

और वर्ग इस तरह दिखता है: जब

var test = JsonConvert.DeserializeObject<Test>(json); 

का उपयोग कर

public class Test 
{ 
    public float? x { get; set; } 
} 

और कोई अपवाद नहीं फेंक दिया गया है, JSON.NET बस स्ट्रिंग मान "50" को फ्लोट वैल्यू 50.0 में परिवर्तित करता है।

यह प्रश्न इनपुट-सत्यापन के संदर्भ में उठाया गया है। मैं अपवाद प्राप्त करना चाहता हूं, क्योंकि JSON स्ट्रिंग अनुबंध का पालन नहीं करती है (x फ़ील्ड वास्तविक फ़्लोट होना चाहिए)।

और मैं 'टेस्ट' कक्षा में संपत्ति एनोटेशन का उपयोग नहीं करना चाहता हूं।

क्या कोई JsonSerializerSettings है जिसका उपयोग इस से बचने के लिए किया जा सकता है?

+0

आप चिह्नित कर सकते हैं '[JsonIgnore] 'विशेषता –

+6

के साथ प्रचार क्या _do_ आप होना चाहते हैं? – CodeCaster

+0

@ZdeslavVojkovic - मैं गलत हो सकता हूं, लेकिन मुझे लगता है कि ओपी इसे अनदेखा करना चाहता है * क्योंकि * यह उद्धरणों में है। यदि हां, तो ओपी, यह निश्चित रूप से धारावाहिक आउटपुट और उपभोक्ता की अपेक्षाओं के बीच एक मेल नहीं है? क्या यह डिजाइन विचार पर अधिक नहीं है? –

उत्तर

5

JSON.NET उदारतापूर्वक नंबर-इन-स्ट्रिंग्स ("50") संख्याओं के रूप में पार्स करता है। जहां तक ​​मुझे मिल सकता है, इसे बंद करने का कोई छोटा रास्ता नहीं है।

public class NumberConverter : JsonConverter 
{ 
    private readonly Type[] _typesNotToReadAsString = { typeof(float), typeof(float?) }; 

    public override bool CanConvert(Type objectType) 
    { 
     return _typesNotToReadAsString.Any(t => t.IsAssignableFrom(objectType)); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JToken token = JToken.Load(reader); 

     if (_typesNotToReadAsString.Contains(objectType) && token.Type == JTokenType.String) 
     { 
      string exceptionString = string.Format("Won't convert string to type {0}", objectType.FullName); 
      throw new JsonSerializationException(exceptionString); 
     } 

     return token.ToObject(objectType); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override bool CanWrite 
    { 
     get { return false; } 
    } 
} 

कनवर्टर रिपोर्ट इस मामले float और float?, लेकिन विन्यास में निर्दिष्ट प्रकार में deserialize करने के लिए, सक्षम होने के लिए:

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

deserialization पर, यह टोकन प्रकार का निरीक्षण करता है। दिए गए JSON इनपुट के लिए कुछ टोकन प्रकार:

  • "50": JTokenType.String
  • 50: JTokenType.Integer
  • 42.1415: JTokenType.Float

इस तरह कनवर्टर लगा सकते हैं कि वर्तमान निशानी के रूप में वांछित स्वरूपित है। जब टोकन प्रकार एक स्ट्रिंग होता है, तो उपरोक्त कनवर्टर एक अपवाद फेंक देगा जिसमें कहा गया है कि यह स्ट्रिंग को वांछित प्रकार में परिवर्तित नहीं करेगा।

जब टोकन प्रकार कुछ और है, कनवर्टर टोकन को उचित संख्यात्मक प्रकार में token.ToObject(objectType) के माध्यम से परिवर्तित करेगा। यह विधि उचित अपवाद फेंककर गैर-संख्यात्मक इनपुट को भी संभालती है, उदाहरण के लिए "ऐरे को एकल में परिवर्तित नहीं किया जा सकता है।"

एक वर्ग Foo को देखते हुए:

public class Foo 
{ 
    public float Bar { get; set; } 
    public string Baz { get; set; } 
    public float? Qux { get; set; } 
} 

कनवर्टर ऊपर का उपयोग कर JSON स्ट्रिंग deserialize, इस काम करेगा:

var jsonString = "{ \"Bar\" : 50, \"Baz\" : \"zaB\", \"Qux\" : 42.1415 }"; 
var foo = JsonConvert.DeserializeObject<Foo>(jsonString, new NumberConverter()); 

इस फेंक करते हैं:

var jsonString = "{ \"Bar\" : 50, \"Baz\" : \"zaB\", \"Qux\" : \"42.1415\" }"; 
var foo2 = JsonConvert.DeserializeObject<Foo>(jsonString, new NumberConverter()); 
संबंधित मुद्दे