2012-02-28 9 views
18

Json.Net का उपयोग करते समय, मैं समझता हूं कि रेंडर जेसन में $ प्रकार की संपत्ति कैसे प्राप्त करें, लेकिन क्या उस फ़ील्ड नाम को बदलने का कोई तरीका है? मुझे "$ प्रकार" के बजाय "__type" का उपयोग करने की आवश्यकता है।

+0

मुझे इसकी भी आवश्यकता है, उदाहरण के लिए [JSON-LD] (http://json-ld.org) '@ type' –

उत्तर

12

ऐसा लगता है कि public const string TypePropertyName = "$type";Newtonsoft.Json.Serialization.JsonTypeReflector में हार्डकोड किया गया है जो दुर्भाग्यवश आंतरिक स्थैतिक वर्ग है।

मुझे इसकी आवश्यकता है, और केवल एक चीज जिसे मैं सोच सकता हूं वह json.net के कस्टम संशोधित संस्करण में है। जो निश्चित रूप से एक प्रमुख पिटा है।

+4

का उपयोग करता है दुर्भाग्यवश, मुझे उस पथ को पूरी तरह से त्यागना पड़ा था जिसके कारण मैं नीचे जा रहा था कई मामलों में जेसन.Net का उपयोग करना कितना मुश्किल है। यह तो केवल एक उदाहरण है। –

+0

मैं खुद को देख रहा हूं कि मैं सर्वर-साइड पर कैसे हूं, जिसे मैंने सी # लिखा है और जेसन.नेट का उपयोग करता है, जेएसओएन का उपयोग करके एंड्रॉइड ऐप से जेएसओएन को भेज दिया जा सकता है। जैक्सन में मैं "$ प्रकार" का उपयोग करने के लिए सेटअप कर सकता हूं, लेकिन यह वैसे भी काम नहीं करता है। – Ted

13

http://json.codeplex.com/workitem/22429

"मैं नहीं बल्कि रखना $ कठिन कोडित टाइप करेंगे और लगातार।"

मुझे क्या आश्चर्य है?

http://json.codeplex.com/workitem/21989

मैं करूंगा बल्कि नहीं - मुझे लगता है कि यह मेरे लिए बहुत विशिष्ट है और मैं सेटिंग्स के साथ पानी में गिर जाने के लिए नहीं करना चाहती। कुछ बिंदु पर मैं शायद कार्यान्वित करूँगा - http://json.codeplex.com/workitem/21856 - लोगों को जेएसओएन में अपने मेटा गुणों को पढ़ने/लिखने की अनुमति देता है और आप किसी नए प्रॉपर्टी नाम के साथ टाइप नाम हैंडलिंग को पुन: कार्यान्वित कर सकते हैं। अन्य विकल्प केवल आपके लिए है कि संपत्ति का नाम रखने के लिए स्रोत कोड को संशोधित करना है।

यह मेरा समाधान है ...

json.Replace("\"$type\": \"", "\"type\": \""); 
+0

आपका समाधान कमाल है!^_^ –

+0

यह भी देखें: https://github.com/JamesNK/Newtonsoft.Json/issues/1331 – manuc66

3

हम इस बात के लिए की जरूरत थी तो मैं एक कस्टम JsonReader बनाया। हम जटिल एमएस वेब सेवाओं में आराम से डेटा मॉडलों के साथ आराम कर रहे हैं और "__type" संपत्ति को "$ प्रकार" के साथ बदलने की आवश्यकता है।

class MSJsonReader : JsonTextReader 
{ 
    public MSJsonTextReader(TextReader reader) : base(reader) { } 

    public override bool Read() 
    { 
     var hasToken = base.Read(); 

     if (hasToken && base.TokenType == JsonToken.PropertyName && base.Value != null && base.Value.Equals("__type")) 
      base.SetToken(JsonToken.PropertyName, "$type"); 

     return hasToken; 
    } 
} 

यहां हम इसका उपयोग कैसे करते हैं।

using(JsonReader jr = new MSJsonTextReader(sr)) 
{ 
    JsonSerializer s = new JsonSerializer(); 
    s.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat; 
    s.NullValueHandling = NullValueHandling.Ignore; 
    s.TypeNameHandling = TypeNameHandling.Auto; // Important! 
    s.Binder = new MSRestToJsonDotNetSerializationBinder("Server.DataModelsNamespace", "Client.GeneratedModelsNamespace"); 

    T deserialized = s.Deserialize<T>(jr); 

    return deserialized; 
} 

यहाँ हमारे MSRestToJsonDotNetSerializationBinder कि एमएस आराम और Json.Net के बीच संगतता पूरा करता है।

class MSRestToJsonDotNetSerializationBinder : System.Runtime.Serialization.SerializationBinder 
{ 
    public string ServiceNamespace { get; set; } 
    public string LocalNamespace { get; set; } 

    public MSRestToJsonDotNetSerializationBinder(string serviceNamespace, string localNamespace) 
    { 
     if (serviceNamespace.EndsWith(".")) 
      serviceNamespace = serviceNamespace.Substring(0, -1); 

     if(localNamespace.EndsWith(".")) 
      localNamespace = localNamespace.Substring(0, -1); 

     ServiceNamespace = serviceNamespace; 
     LocalNamespace = localNamespace; 
    } 

    public override void BindToName(Type serializedType, out string assemblyName, out string typeName) 
    { 
     assemblyName = null; 
     typeName = string.Format("{0}:#{1}", serializedType.Name, ServiceNamespace); // MS format 
    } 

    public override Type BindToType(string assemblyName, string typeName) 
    { 
     string jsonDotNetType = string.Format("{0}.{1}", LocalNamespace, typeName.Substring(0, typeName.IndexOf(":#"))); 
     return Type.GetType(jsonDotNetType); 
    } 
} 
1

एक और विकल्प है कि Json.NET में कस्टम प्रकार संपत्ति नाम क्रमानुसार करने की अनुमति देता है नहीं है। विचार डिफ़ॉल्ट $type संपत्ति नहीं लिखता है, लेकिन प्रकार का नाम कक्षा की संपत्ति के रूप में पेश करता है।

मान लीजिए हम एक Location वर्ग है:

public class Location 
{ 
    [JsonProperty("__type")] 
    public string EntityTypeName 
    { 

     get 
     { 
      var typeName = string.Format("{0}, {1}", GetType().FullName, GetType().Namespace); 
      return typeName; 
     } 
    } 

    public double Latitude { get; set; } 

    public double Longitude { get; set; } 
} 

फिर, TypeNameHandling.None को JsonSerializerSettings.TypeNameHandling सेट:

public class Location 
{ 
    public double Latitude { get; set; } 

    public double Longitude { get; set; } 
} 

सबसे पहले, हम जैसा कि नीचे बताया प्रकार संपत्ति नाम लागू करने और वर्ग संशोधित करने की आवश्यकता deserializer डिफ़ॉल्ट $type विशेषता के प्रतिपादन को छोड़ने के क्रम में।

यही है।

उदाहरण

var point = new Location() { Latitude = 51.5033630, Longitude = -0.1276250 }; 

var jsonLocation = JsonConvert.SerializeObject(point, new JsonSerializerSettings 
{ 
    TypeNameHandling = TypeNameHandling.None, //do not write type property(!) 
}); 
Console.WriteLine(jsonLocation); 

परिणाम

{"__type":"Namespace.Location, Namespace","Latitude":51.503363,"Longitude":-0.127625} 
+0

मुझे नहीं पता कि कैसे deserializing आपके समाधान के साथ सही प्रकार निर्धारित करेगा। क्या तुम समझा सकते हो? –

+0

deserialize करने के लिए, 'JsonCreationConverter', उदाहरण का प्रयास करें http://stackoverflow.com/questions/8030538 देखें – xmedeko

2

जब serializing, वहाँ संपत्ति नाम ओवरराइड करने के लिए एक अच्छा तरीका है:

public class CustomJsonWriter : JsonTextWriter 
{ 
    public CustomJsonWriter(TextWriter writer) : base(writer) 
    { 
    } 

    public override void WritePropertyName(string name, bool escape) 
    { 
     if (name == "$type") name = "__type"; 
     base.WritePropertyName(name, escape); 
    } 
} 

var serializer = new JsonSerializer(); 
var writer = new StreamWriter(stream) { AutoFlush = true }; 
serializer.Serialize(new CustomJsonWriter(writer), objectToSerialize); 

मैं प्रयास नहीं किया है deserialization अभी तक, लेकिन सबसे खराब स्थिति में मैं इस्तेमाल कर सकते हैं:

json.Replace("\"__type": \"", "\"type\": \"$type\"); 
2

मैं अपने यूआई बाकी एपीआई के लिए यह करने के लिए किया था एक डॉलर चिह्न ($) के साथ शुरू Angular.js disregards क्षेत्रों नामों के रूप में।

तो यहाँ एक समाधान है कि पूरे वेब एपीआई के लिए __type करने के लिए $type नाम बदलता है और दोनों क्रमबद्धता और अक्रमांकन के लिए काम करता है।

आदेश में एक कस्टम JsonWriter और एक कस्टम का उपयोग करने में सक्षम होना JsonReader (के रूप में इस सवाल का अन्य उत्तर में प्रस्तावित), हम JsonMediaTypeFormatter वारिस और इसी के तरीकों को ओवरराइड करने के लिए है:

internal class CustomJsonNetFormatter : JsonMediaTypeFormatter 
{ 
    public override JsonReader CreateJsonReader(Type type, Stream readStream, Encoding effectiveEncoding) 
    { 
     return new CustomJsonReader(readStream, effectiveEncoding); 
    } 

    public override JsonWriter CreateJsonWriter(Type type, Stream writeStream, Encoding effectiveEncoding) 
    { 
     return new CustomJsonWriter(writeStream, effectiveEncoding); 
    } 

    private class CustomJsonWriter : JsonTextWriter 
    { 
     public CustomJsonWriter(Stream writeStream, Encoding effectiveEncoding) 
      : base(new StreamWriter(writeStream, effectiveEncoding)) 
     { 
     } 

     public override void WritePropertyName(string name, bool escape) 
     { 
      if (name == "$type") name = "__type"; 
      base.WritePropertyName(name, escape); 
     } 
    } 

    private class CustomJsonReader : JsonTextReader 
    { 
     public CustomJsonReader(Stream readStream, Encoding effectiveEncoding) 
      : base(new StreamReader(readStream, effectiveEncoding)) 
     { 
     } 

     public override bool Read() 
     { 
      var hasToken = base.Read(); 
      if (hasToken && TokenType == JsonToken.PropertyName && Value != null && Value.Equals("__type")) 
      { 
       SetToken(JsonToken.PropertyName, "$type"); 
      } 
      return hasToken; 
     } 
    } 
} 
के

पाठ्यक्रम आपको अपने WebApiConfig में कस्टम फॉर्मेटर पंजीकृत करने की आवश्यकता है। इसलिए हम अपने कस्टम एक साथ डिफ़ॉल्ट Json.NET फ़ॉर्मेटर बदल देते हैं:

config.Formatters.Remove(config.Formatters.JsonFormatter); 
config.Formatters.Add(new CustomJsonNetFormatter()); 

हो गया।

[JsonConverter(typeof(JsonSubtypes), "ClassName")] 
public class Annimal 
{ 
    public virtual string ClassName { get; } 
    public string Color { get; set; } 
} 

आप JsonSubtypes कनवर्टर कि Newtonsoft.Json परियोजना का हिस्सा नहीं है की आवश्यकता होगी:

0

आप भी इसे इस तरह से कर सकता है।

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