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




asp.net json (16)

ओमर बोखारी और यूरी के उत्तरों का संयोजन अलगाव मेरे समाधान के बाद से है जो मैं प्रदान करना चाहता हूं, आमतौर पर मेरे एनम में जो कुछ है, उससे अलग है, विशेष रूप से मैं अपने enums को बदलने में सक्षम होना चाहता हूं।

तो अगर कोई दिलचस्पी लेता है, तो ऐसा कुछ है:

public enum Gender
{
   [EnumMember(Value = "male")] 
   Male,
   [EnumMember(Value = "female")] 
   Female
}

class Person
{
    int Age { get; set; }
    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}

मेरे पास एक कक्षा है जिसमें एक 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" }

नेट कोर वेब एपीआई के लिए: -

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddJsonFormatters(f => f.Converters.Add(new 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


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

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

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; }

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

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

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


मैंने पाया है कि Json.NET एक सटीक कार्यक्षमता प्रदान करता है जिसे मैं StringEnumConverter विशेषता के साथ StringEnumConverter रहा हूं:

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

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

StringEnumConverter दस्तावेज़ीकरण पर उपलब्ध अधिक जानकारी।


यहां एक सरल समाधान है जो जेएसओएन के लिए सर्वर-साइड सी # एनम को क्रमबद्ध करता है और क्लाइंट-साइड <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>

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

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

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

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

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

अगर किसी को उपर्युक्त अपर्याप्त लगता है, तो मैं इस अधिभार के साथ निपटने के लिए समाप्त हो गया:

JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter())

यह एक पुराना सवाल है, लेकिन मैंने सोचा कि मैं सिर्फ मामले में योगदान दूंगा। मेरी परियोजनाओं में मैं किसी भी जेसन अनुरोध के लिए अलग मॉडल का उपयोग करता हूं। एक मॉडल आमतौर पर "जेसन" उपसर्ग के साथ डोमेन ऑब्जेक्ट के समान नाम होगा। मॉडल ऑटोमैपर का उपयोग करके मैप किए गए हैं। जेसन मॉडल को एक स्ट्रिंग प्रॉपर्टी घोषित करने के लिए जो डोमेन क्लास पर एक enum है, ऑटोमैपर इसकी स्ट्रिंग प्रेजेंटेशन को हल करेगा।

यदि आप सोच रहे हैं, तो मुझे जेसन सीरियलाइज्ड कक्षाओं के लिए अलग-अलग मॉडल की आवश्यकता है क्योंकि इनबिल्ट सीरियलाइज़र अन्यथा परिपत्र संदर्भों के साथ आता है।

उम्मीद है कि यह किसी की मदद करता है।


स्ट्रिंग के रूप में c # enum के JSON serialization के लिए नीचे अपने global.asax में जोड़ें

  HttpConfiguration config = GlobalConfiguration.Configuration;
            config.Formatters.JsonFormatter.SerializerSettings.Formatting =
                Newtonsoft.Json.Formatting.Indented;

            config.Formatters.JsonFormatter.SerializerSettings.Converters.Add
                (new Newtonsoft.Json.Converters.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 की सुविधाओं और कार्यक्षमताओं की तुलना में एक लिंक यहां दिया गया है


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]  
);

@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
}






javascriptserializer