c# - स्ट्रिंग के रूप में enum के जेएसओएन serialization




asp.net json (13)

मेरे पास एक कक्षा है जिसमें एक enum संपत्ति है, और JavaScriptSerializer का उपयोग कर ऑब्जेक्ट को क्रमबद्ध करने पर, मेरे जेसन परिणाम में इसकी string "नाम" की बजाय गणना का पूर्णांक मान होता है। क्या कस्टम JavaScriptConverter कनवर्टर बनाने के बिना मेरे जेसन में string रूप में enum प्राप्त करने का कोई तरीका है? शायद एक विशेषता है कि मैं enum परिभाषा, या वस्तु संपत्ति, सजाने के साथ सजाने सकता है?

उदहारण के लिए:

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }
    Gender Gender { get; set; }
}

वांछित जेसन परिणाम:

{ "Age": 35, "Gender": "Male" }

@Iggy उत्तर सी # एनम के जेएसओएन क्रमबद्धता को केवल एएसपी.नेट (वेब ​​एपीआई और इसलिए) के लिए स्ट्रिंग के रूप में सेट करता है।

लेकिन इसे विज्ञापन क्रमबद्धता के साथ भी काम करने के लिए, अपनी प्रारंभिक कक्षा में निम्नलिखित जोड़ें (जैसे Global.asax Application_Start)

//convert Enums to Strings (instead of Integer) globally
JsonConvert.DefaultSettings = (() =>
{
    var settings = new JsonSerializerSettings();
    settings.Converters.Add(new StringEnumConverter { CamelCaseText = true });
    return settings;
});

Json.NET पृष्ठ पर अधिक जानकारी

इसके अतिरिक्त, अपने एनम सदस्य को विशिष्ट पाठ से क्रमबद्ध / deserialize करने के लिए, का उपयोग करें

System.Runtime.Serialization.EnumMember

विशेषता, इस तरह:

public enum time_zone_enum
{
    [EnumMember(Value = "Europe/London")] 
    EuropeLondon,

    [EnumMember(Value = "US/Alaska")] 
    USAlaska
}

Newtonsoft.json का उत्तर यहां दिया गया है

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}

आप JsonConializerSettings को JsonConverter.SerializeObject पर कॉल के साथ नीचे बना सकते हैं:

var result = JsonConvert.SerializeObject
            (
                dataObject,
                new JsonSerializerSettings
                {
                    Converters = new [] {new StringEnumConverter()}
                }
            );

आप वास्तव में अंतर्निहित जावास्क्रिप्टसेरियलाइज़र के साथ इसे पूरा करने के लिए जावास्क्रिप्ट कनवर्टर का उपयोग कर सकते हैं। अपने एनम को उरी में परिवर्तित करके आप इसे एक स्ट्रिंग के रूप में एन्कोड कर सकते हैं।

मैंने वर्णन किया है कि यह तिथियों के लिए कैसे करें लेकिन इसका उपयोग enums के लिए भी किया जा सकता है।

http://blog.calyptus.eu/seb/2011/12/custom-datetime-json-serialization/


कोई विशेष विशेषता नहीं है जिसका आप उपयोग कर सकते हैं। JavaScriptSerializer अपने संख्यात्मक मानों के लिए enums क्रमबद्ध करता है और उनके स्ट्रिंग प्रतिनिधित्व नहीं। आपको एनमेर को क्रमिक मूल्य के बजाय इसके नाम के रूप में क्रमबद्ध करने के लिए कस्टम क्रमिकरण का उपयोग करना होगा।

संपादित करें: जैसा कि @OmerBakhari JSON.net द्वारा इंगित किया गया है, इस उपयोग के मामले को कवर करता है (विशेषता [JsonConverter(typeof(StringEnumConverter))] और कई अन्य लोगों ने अंतर्निहित [JsonConverter(typeof(StringEnumConverter))] serializers द्वारा प्रबंधित नहीं किया है। Serializers की सुविधाओं और कार्यक्षमताओं की तुलना में एक लिंक यहां दिया गया है


ध्यान दिया गया है कि वर्णन विशेषता होने पर क्रमिकरण के लिए कोई जवाब नहीं है।

यहां मेरा कार्यान्वयन है जो विवरण विशेषता का समर्थन करता है।

public class CustomStringEnumConverter : Newtonsoft.Json.Converters.StringEnumConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Type type = value.GetType() as Type;

        if (!type.IsEnum) throw new InvalidOperationException("Only type Enum is supported");
        foreach (var field in type.GetFields())
        {
            if (field.Name == value.ToString())
            {
                var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
                writer.WriteValue(attribute != null ? attribute.Description : field.Name);

                return;
            }
        }

        throw new ArgumentException("Enum not found");
    }
}

enum:

public enum FooEnum
{
    // Will be serialized as "Not Applicable"
    [Description("Not Applicable")]
    NotApplicable,

    // Will be serialized as "Applicable"
    Applicable
}

उपयोग:

[JsonConverter(typeof(CustomStringEnumConverter))]
public FooEnum test { get; set; }

मैं स्रोत मॉडल को शीर्ष उत्तर (@ob।) की तरह बदलने में सक्षम नहीं था, और मैं इसे वैश्विक रूप से @Iggy जैसे पंजीकृत नहीं करना चाहता था। तो मैंने SerializeObject कमांड के दौरान स्ट्रिंग एनम कनवर्टर को सेट करने की अनुमति देने के लिए https://.com/a/2870420/237091 और @ Iggy's https://.com/a/18152942/237091 संयुक्त किया:

Newtonsoft.Json.JsonConvert.SerializeObject(
    objectToSerialize, 
    Newtonsoft.Json.Formatting.None, 
    new Newtonsoft.Json.JsonSerializerSettings()
    {
        Converters = new List<Newtonsoft.Json.JsonConverter> {
            new Newtonsoft.Json.Converters.StringEnumConverter()
        }
    })

मैंने Newtonsoft.Json लाइब्रेरी का उपयोग करके इस समाधान के सभी टुकड़ों को एक साथ रखा है। यह enum मुद्दा को हल करता है और त्रुटि को बेहतर तरीके से संभालने में भी बनाता है, और यह आईआईएस होस्टेड सेवाओं में काम करता है। यह बहुत सारे कोड है, इसलिए आप इसे यहां गिटहब पर पा सकते हैं: https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs

इसे अपने Web.config काम करने के लिए कुछ प्रविष्टियां जोड़नी Web.config , आप यहां एक उदाहरण फ़ाइल देख सकते हैं: https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config


यदि आप JsonSerializer कनवर्टर विशेषता का उपयोग नहीं करना चाहते हैं तो आप अपने JsonSerializer कनवर्टर भी जोड़ सकते हैं:

string SerializedResponse = JsonConvert.SerializeObject(
     objToSerialize, 
     new Newtonsoft.Json.Converters.StringEnumConverter()
); 

यह उस क्रमिकरण के दौरान देखे जाने वाले प्रत्येक enum लिए काम करेगा।


यह आसानी से Gender संपत्ति में ScriptIgnore विशेषता जोड़कर किया जाता है, जिसके कारण इसे क्रमबद्ध नहीं किया जाता है, और एक GenderString प्रॉपर्टी GenderString है जो क्रमबद्ध होती है:

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

    string GenderString { get { return Gender.ToString(); } }
}

यहां एक सरल समाधान है जो जेएसओएन के लिए सर्वर-साइड सी # एनम को क्रमबद्ध करता है और क्लाइंट-साइड <select> element को पॉप्युलेट करने के परिणाम का उपयोग करता है। यह सरल enums और bitflag enums दोनों के लिए काम करता है।

मैंने एंड-टू-एंड समाधान शामिल किया है क्योंकि मुझे लगता है कि जेएसओएन को सी # एनम को क्रमबद्ध करने के इच्छुक अधिकांश लोग शायद <select> ड्रॉप-डाउन भरने के लिए इसका उपयोग करेंगे।

यहाँ जाता हैं:

उदाहरण एनम

public enum Role
{
    None = Permission.None,
    Guest = Permission.Browse,
    Reader = Permission.Browse| Permission.Help ,
    Manager = Permission.Browse | Permission.Help | Permission.Customise
}

एक जटिल enum जो अनुमति प्रणाली उत्पन्न करने के लिए bitwise ORs का उपयोग करता है। तो आप enum के पूर्णांक मान के लिए सरल सूचकांक [0,1,2 ..] पर भरोसा नहीं कर सकते हैं।

सर्वर साइड - सी #

Get["/roles"] = _ =>
{
    var type = typeof(Role);
    var data = Enum
        .GetNames(type)
        .Select(name => new 
            {
                Id = (int)Enum.Parse(type, name), 
                Name = name 
            })
        .ToArray();

    return Response.AsJson(data);
};

उपरोक्त कोड प्राप्त अनुरोध को संभालने के लिए नैन्सीएफएक्स ढांचे का उपयोग करता है। यह नैन्सी के Response.AsJson() सहायक विधि का उपयोग करता है - लेकिन चिंता न करें, आप किसी भी मानक JSON फॉर्मेटर का उपयोग कर सकते हैं क्योंकि enum पहले से ही एक सरल अज्ञात प्रकार में प्रक्षेपण के लिए तैयार किया गया है।

जेनरेट जेएसओएन

[
    {"Id":0,"Name":"None"},
    {"Id":2097155,"Name":"Guest"},
    {"Id":2916367,"Name":"Reader"},
    {"Id":4186095,"Name":"Manager"}
]

क्लाइंट साइड - कॉफीस्क्रिप्ट

fillSelect=(id, url, selectedValue=0)->
    $select = $ id
    $option = (item)-> $ "<option/>", 
        {
            value:"#{item.Id}"
            html:"#{item.Name}"
            selected:"selected" if item.Id is selectedValue
        }
    $.getJSON(url).done (data)->$option(item).appendTo $select for item in data

$ ->
    fillSelect "#role", "/roles", 2916367

पहले एचटीएमएल

<select id="role" name="role"></select>

एचटीएमएल के बाद

<select id="role" name="role">
    <option value="0">None</option>
    <option value="2097155">Guest</option>
    <option value="2916367" selected="selected">Reader</option>
    <option value="4186095">Manager</option>
</select>

स्टीफन के answer का यह संस्करण जेएसओएन में नाम नहीं बदलता है:

[DataContract(
    Namespace = 
       "http://schemas.datacontract.org/2004/07/Whatever")]
class Person
{
    [DataMember]
    int Age { get; set; }

    Gender Gender { get; set; }

    [DataMember(Name = "Gender")]
    string GenderString
    {
        get { return this.Gender.ToString(); }
        set 
        { 
            Gender g; 
            this.Gender = Enum.TryParse(value, true, out g) ? g : Gender.Male; 
        }
    }
}

new JavaScriptSerializer().Serialize(  
    (from p   
    in (new List<Person>() {  
        new Person()  
        {  
            Age = 35,  
            Gender = Gender.Male  
        }  
    })  
    select new { Age =p.Age, Gender=p.Gender.ToString() }  
    ).ToArray()[0]  
);




javascriptserializer