JavaScriptSerializer - स्ट्रिंग के रूप में JSON क्रमबद्धता


1160

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

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

enum Gender { Male, Female }

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

वांछित परिणाम:

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

आदर्श रूप से अंतर्निहित .NET फ्रेमवर्क कक्षाओं के साथ उत्तर की तलाश में हैं, यदि संभव नहीं है तो विकल्प (जैसे Json.net) का स्वागत है।


8
किसको बदलें? उच्चतम उत्तोलित उत्तर वास्तव में प्रश्न का उत्तर नहीं देता है - हाँ यह अन्य संदर्भों में उपयोगी है, इसलिए वोट, लेकिन यदि आप MS JavaScriptSerializer के साथ फंसे हुए हैं तो इसका कोई व्यावहारिक उपयोग नहीं है, क्योंकि अनिवार्य रूप से आप पृष्ठ विधियों और , सबसे महत्वपूर्ण बात, सवाल के रूप में आवश्यक है। स्वीकृत उत्तर कहता है कि यह संभव नहीं है। मेरे जवाब के एक हैक का थोड़ा सा काम हो जाता है।
स्टीफन कैनेडी

जवाबों:


374

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


यदि आप OmerBakhari द्वारा प्रदान किए गए इस प्रश्न पर उत्तरJavaScriptSerializer देखने के बजाय JSON.Net का उपयोग कर सकते हैं : JSON.net इस उपयोग के मामले को कवर करता है (विशेषता के माध्यम से ) और कई अन्य जो इन नेट अनुक्रमक में निर्मित नहीं होते हैं। यहाँ धारावाहिकों की सुविधाओं और कार्यात्मकताओं की तुलना करने वाली एक कड़ी है[JsonConverter(typeof(StringEnumConverter))]


7
@Fabzter - अपने समाधान Newtonsoft के JSON का उपयोग कर मेरे साथ काम किया
BeemerGuy

1
@BornToCode Json.NET वह अनुक्रमक है जो ASP.NET डिफ़ॉल्ट रूप से उपयोग करता है।
ब्रेनस्ल्गस 83

12
@ BrainSlugs83 - सवाल JS.NET का उपयोग करने के बारे में था, न कि Json.NET (और यदि आप उन संशोधन इतिहास को देखेंगे तो आप देखेंगे कि वहाँ एक संपादन स्पष्ट किया गया था), यदि आप JavaScriptSerializer का उपयोग करते हैं तो विशेषता JsonConverterकाम नहीं करने वाली है।
बॉर्नटॉक्स कोड

50
कृपया इसे स्वीकार किए गए उत्तर के रूप में हटा दें क्योंकि यह समस्या को हल नहीं करता है, नीचे दिए गए उत्तर 1000+ के साथ आगे बढ़ाता है।
MHGameWork

क्या आप मुझे बता सकते हैं
चेन

2100

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

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

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

पर अधिक जानकारी उपलब्ध है StringEnumConverterप्रलेखन

इस कनवर्टर को विश्व स्तर पर कॉन्फ़िगर करने के लिए अन्य स्थान हैं:

  • enum ही अगर आप चाहते हैं कि enum हमेशा serialized / deserialized स्ट्रिंग के रूप में होना चाहिए:

    [JsonConverter(typeof(StringEnumConverter))]  
    enum Gender { Male, Female }
  • यदि कोई विशेषता सजावट से बचना चाहता है, तो आप कनवर्टर को अपने JsonSerializer ( Bjørn Egcom द्वारा सुझाए गए ) में जोड़ सकते हैं :

    serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); 

    और यह उस क्रमांकन ( ट्रैविस द्वारा सुझाए गए ) के दौरान देखे जाने वाले प्रत्येक एनम के लिए काम करेगा ।

  • या JsonConverter ( केले द्वारा सुझाए गए ):

    JsonConvert.SerializeObject(MyObject, 
        new Newtonsoft.Json.Converters.StringEnumConverter());

इसके अतिरिक्त आप आवरण को नियंत्रित कर सकते हैं और क्या स्ट्रींगइन्कम कनेक्टर (NamingStrategy, बूलियन) कंस्ट्रक्टर का उपयोग करके नंबर अभी भी स्वीकार किए जाते हैं ।


9
विवरण के लिए लिंक का अनुसरण करें कि इसका उपयोग asp.net mvc एप्लिकेशन में कैसे करें। james.newtonking.com/archive/2008/10/16/…
RredCat

2
यहाँ उस फ़ंक्शन का लिंक दिया गया है: james.newtonking.com/projects/json/help/html/…
CAD

61
HttpConfiguration config = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.Converters.Add (नया Newtonsoft.Json.Converters.StringEnumConverter ());
Iggy

1
यह डिफ़ॉल्ट रूप से नोट करने के लिए उपयोगी है। ASP.NET MVC json.Net का उपयोग जेन्स धारावाहिक के रूप में नहीं करता है और Controllerप्रत्येक क्रमांकन को विस्तारित या मैन्युअल रूप से ओवरराइड करने की आवश्यकता होती है ।
ओडीस

2
आप कनवर्टर ( camelCaseआउटपुट के लिए कह सकते हैं) को अनुकूलित कर सकते हैं :new StringEnumConverter { CamelCaseText = true }
सीफिश

172

स्ट्रिंग के रूप में c # enum के JSON क्रमांकन के लिए अपने 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());

4
किसी कारण से, मुझे यह काम करने के लिए नहीं मिल रहा है। फ़िडलर जगह में इस के साथ, 'चेतावनी' के बजाय एक जिद्दी 2 दिखाता है। इसके अलावा - किसी भी कारण से किसको बदलना Formattingहै Indented?
sq33G

5
इस उदाहरण से तीसरी पंक्ति को App_start / webapiconfig.cs फ़ाइल में जोड़ा गया था और REST (json fomat) कॉल्स में एनम मानों के लिए स्ट्रिंग्स वापस करने के लिए ASP.NET वेब API 2.1 प्रोजेक्ट में मेरे लिए एक ट्रिक की।
ग्रेग जेड।

1
क्या केवल अनुरोध स्कोप के अनुसार इस संपत्ति को सेट करने का कोई तरीका है?
एस्तेस किवरनग्लू

@AnestisKivranoglou सिर्फ कस्टम सेटिंग्स के प्रति कस्टम json क्रम का उपयोग करें।
BrainSlugs83

3
ऑपिनेंट की पहली सीरीज़र सेटिंग को op प्रश्न से असंबंधित किया गया है।
user3791372

153

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

लेकिन इसे तदर्थ क्रमांकन के साथ भी काम करने के लिए, अपने प्रारंभ वर्ग में जोड़ें (जैसे 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 पेज पर अधिक जानकारी

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

System.Runtime.Serialization.EnumMember

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

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

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

6
धन्यवाद! मैं बस ढूंढ रहा था [EnumMember]
पोलाद

CamelCaseTextसंपत्ति अब अप्रचलित चिह्नित है। कनवर्टर को त्वरित करने का नया तरीका:new StringEnumConverter(new CamelCaseNamingStrategy())
fiat

बहुत बहुत धन्यवाद, मेरा दिन बना दिया! :)
Eldo Novr

39

मैं शीर्ष उत्तर (@ob।) की तरह स्रोत मॉडल को बदलने में सक्षम नहीं था, और मैं इसे @Iggy जैसे विश्व स्तर पर पंजीकृत नहीं करना चाहता था। इसलिए मैंने SerializeOject कमांड के दौरान स्ट्रिंग एनम कनवर्टर सेट करने की अनुमति देने के लिए https://stackoverflow.com/a/2870420/237091 और @ Iggy का https://stackoverflow.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()
        }
    })

यह भी अच्छा लगता है अगर आपके पास इस सूची की तरह एक संपत्ति है <someEnumType>
बोगडान

34

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

तो अगर किसी को दिलचस्पी है, यह कुछ इस तरह है:

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

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

1
मैं JsonPropertyAttributeएनम सदस्यों के लिए उपयोग कर रहा था और यह सरल deserializtion कार्यों के लिए काम कर रहा है। अफसोस की बात है कि मैनुअल के दौरान JTokenएस के साथ ट्वीक की अनदेखी हो जाती है। हैपली EnumMemberAttributeएक आकर्षण की तरह काम करता है। धन्यवाद!
Prolog

के साथ काम करता है JavaScriptSerializer?
स्टीफन कैनेडी

31

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

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

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

29
मुझे समझाने का प्रयास करने दें। यह समाधान डिजाइन पाटर्स के अनुसार सही नहीं है। आपने दृश्य उद्देश्य के अनुसार मॉडल को संशोधित किया है। लेकिन मॉडल में केवल डेटा होता है और प्रस्तुतियों के बारे में परवाह नहीं की जाती है। आपको इस कार्यक्षमता को दूसरी परत पर ले जाना होगा।
र्रेडकट

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

17
@RredCat "दृश्य मॉडल" में दृश्य-विशिष्ट गुण होने के साथ कुछ भी गलत नहीं है। IMHO की गलती डोमेन मॉडल से व्यू मॉडल को विभाजित नहीं करना होगा: blogs.msdn.com/b/simonince/archive/2010/01/01/26/…
Mariano Desanze

5
@RredCat, भले ही कुछ पैटर्न के अनुसार गलत था, लेकिन ओपी इस बारे में कुछ नहीं कहता है, इसलिए यह वास्तव में एक सही उत्तर है। (यहां तक ​​कि अगर मैं दार्शनिक रूप से आपकी बात से सहमत हो सकता हूं।)
मेमार्क

10
इस कमेंट थ्रेड में बाइक चलाने की बेतुकी आकर्षक बातें हैं।
माइक मूनी

26

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

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

3
मेरा मानना है कि इस के लिए मान्य है DataContractJsonSerializerनहींJavaScriptSerializer
KCD

सरल और देशी .NET फ्रेमवर्क धारावाहिकों का उपयोग करके मेरे लिए समस्या हल करता है।
सीनेटर

मेरे लिए सबसे अच्छा समाधान है क्योंकि मुझे तीसरे पक्ष के पुस्तकालयों (आईएसओ जटिलता के मुद्दों) का उपयोग करने की अनुमति नहीं है
डैनियल ग्रूसज़िक

यह पाठ्यक्रम के प्रश्न में धारावाहिक के प्रकार के लिए नहीं है। JavaScriptSerializer सब कुछ अनदेखा कर देता है, जबकि DataContractJsonSerializer को DataMember विशेषताओं की आवश्यकता होती है। बाहर चिल्लाने के लिए धन्यवाद, लेकिन कृपया ध्यान दें कि आपने मेरा नाम गलत लिखा है :)
स्टीफन केनेडी

25

यहाँ newtonsoft.json के लिए जवाब है

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

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

1
इस उत्तर के लिए धन्यवाद, मेरी बहुत मदद की! यदि आप PascalCase में अपनी दुश्मनी को परिभाषित करना चाहते हैं, लेकिन आप चाहते हैं कि इसे CamelCase में क्रमांकित किया जाए तो आपको trueअपने JsonConverter प्रकार को इस तरह जोड़ना होगा:[JsonConverter(typeof(StringEnumConverter), true)]
Peet


16

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

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

यह हर enumउस धारावाहिक के दौरान देखने के लिए काम करेगा ।


15

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

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

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

उदाहरण एनुम

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

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

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

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 फॉर्मैटर का उपयोग कर सकते हैं क्योंकि एनम पहले से ही क्रमांकन के लिए तैयार एक साधारण अनाम प्रकार में पेश किया गया है।

जेनसन बनाया

[
    {"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

HTML से पहले

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

HTML के बाद

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

13

ASP.Net कोर के लिए बस अपने स्टार्टअप क्लास में निम्नलिखित जोड़ें:

JsonConvert.DefaultSettings = (() =>
        {
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new StringEnumConverter { AllowIntegerValues = false });
            return settings;
        });

1
यह सभी संस्करणों के लिए काम करता है, न कि केवल कोर।
bikeman868

11

आप नीचे दिए गए JsonConverter.SerializeObject पर कॉल के साथ JsonSerializerSettings बना सकते हैं:

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

10

वर्णन विशेषता होने पर क्रमिकता के लिए कोई उत्तर नहीं है।

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

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

10

.Net कोर के लिए: -

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));
    ...
}

2
यदि यह Microsoft.AspNetCore.Mvc.Formatters.JsonNuGet पैकेज से एक है , तो यह केवल एक एक्सटेंशन पद्धति है IMvcCoreBuilder, पर नहीं IMvcBuilder। इसलिए इसका उपयोग किया जाता है services.AddMvcCore().AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));
फ्लावरएक्सएक्स

9

इननेट कोर 3 में अब यह System.Text.Json में अंतर्निहित कक्षाओं के साथ संभव है:

var person = new Person();
// Create and add a converter which will use the string representation instead of the numeric value.
var stringEnumConverter = new System.Text.Json.Serialization.JsonStringEnumConverter();
JsonSerializerOptions opts = new JsonSerializerOptions();
opts.Converters.Add(stringEnumConverter);
// Generate json string.
var json = JsonSerializer.Serialize<Person>(person, opts);

JsonStringEnumConverterविशिष्ट संपत्ति के लिए विशेषता सजावट के साथ कॉन्फ़िगर करने के लिए:

using System.Text.Json.Serialization;

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

यदि आप हमेशा एनम को स्ट्रिंग के रूप में परिवर्तित करना चाहते हैं, तो विशेषता को एनम पर रखें।

[JsonConverter(typeof(JsonStringEnumConverter))] 
enum Gender { Male, Female }

9

Asp.Net Core 3 System.Text.Json के साथ

public void ConfigureServices(IServiceCollection services)
{

    services
        .AddControllers()
        .AddJsonOptions(options => 
           options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())
        );

    //...
 }

8

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

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

यह मेरे वर्तमान उपयोग के मामले के लिए एक अच्छा समाधान है: मैं धारावाहिकों की चूक को बदलना नहीं चाहता और मुझे विशेषताओं का उपयोग करने में समस्या है, क्योंकि मेरे गुण टाइप IList <EnumType> के हैं।
डर्क ब्रोकहॉस

5

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

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

आशा है कि यह किसी की मदद करता है।


आटोमैपर की उस विशेषता को जानकर अच्छा लगा ;-) [ScriptIgnore] विशेषता परिपत्र संदर्भों को हटा देगी
ledragon

1
ओह। विशेषता के बारे में पता नहीं था। धन्यवाद! आप अपने Pocos पर उपयोग करेंगे? मैंने किसी भी पोको विशेषताओं के लिए मेटाडेटा टाइप परिभाषाओं का उपयोग करने के लिए सिर्फ उन्हें साफ रखने का सहारा लिया है। क्या विशेषता अभी भी मेटा डेटा के माध्यम से काम करेगी?
एल्स पोटोकनिक हाहोनिना

3

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

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


बहुत ही रोचक उपाय! साझा करने के लिए धन्यवाद।
ओलिवर

1

सुनिश्चित नहीं है कि यह अभी भी प्रासंगिक है, लेकिन मुझे सीधे एक json फ़ाइल में लिखना था और मैं निम्नलिखित स्टैकओवरफ़्लो के एक साथ जवाब देने के साथ आया था

public class LowercaseJsonSerializer
{
    private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        ContractResolver = new LowercaseContractResolver()
    };

    public static void Serialize(TextWriter file, object o)
    {
        JsonSerializer serializer = new JsonSerializer()
        {
            ContractResolver = new LowercaseContractResolver(),
            Formatting = Formatting.Indented,
            NullValueHandling = NullValueHandling.Ignore
        };
        serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
        serializer.Serialize(file, o);
    }

    public class LowercaseContractResolver : DefaultContractResolver
    {
        protected override string ResolvePropertyName(string propertyName)
        {
            return Char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1);
        }
    }
}

यह विश्वास दिलाता है कि मेरी सभी json कुंजियाँ json "नियमों" के अनुसार शुरू होती हैं। प्रारूप इसे साफ-सुथरा इंडेंट करता है और आउटपुट में नल की उपेक्षा करता है। StringEnumConverter को जोड़कर यह उनके स्ट्रिंग मान के साथ प्रिंट करता है।

व्यक्तिगत रूप से मुझे यह सबसे साफ लगता है कि मैं एनोटेशन के साथ मॉडल को गंदा किए बिना, साथ आ सकता था।

उपयोग:

    internal void SaveJson(string fileName)
    {
        // serialize JSON directly to a file
        using (StreamWriter file = File.CreateText(@fileName))
        {
            LowercaseJsonSerializer.Serialize(file, jsonobject);
        }
    }

0

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

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


0

और VB.net के लिए मुझे निम्नलिखित काम मिले:

Dim sec = New Newtonsoft.Json.Converters.StringEnumConverter()
sec.NamingStrategy() = New Serialization.CamelCaseNamingStrategy

Dim JSON_s As New JsonSerializer
JSON_s.Converters.Add(sec)

Dim jsonObject As JObject
jsonObject = JObject.FromObject(SomeObject, JSON_s)
Dim text = jsonObject.ToString

IO.File.WriteAllText(filePath, text)

0

थोड़ा और भविष्य के सबूत का विकल्प

एक ही सवाल का सामना करते हुए, हमने निर्धारित किया कि हमें StringEnumConverterयह सुनिश्चित करने के लिए एक कस्टम संस्करण की आवश्यकता है कि हमारे एनुम मान समय पर विस्तार कर सकते हैं बिना deserializing पक्ष पर (नीचे पृष्ठभूमि देखें)। का उपयोग करते हुएSafeEnumConverterनीचे दिए गए डीरियलाइज़ेशन को समाप्त करने की अनुमति मिलती है, भले ही पेलोड में एनम के लिए एक मान होता है, जिसका नाम परिभाषा नहीं है, इंट-टू-एनम रूपांतरण कैसे काम करेगा।

उपयोग:

[SafeEnumConverter]
public enum Colors
{
    Red,
    Green,
    Blue,
    Unsupported = -1
}

या

[SafeEnumConverter((int) Colors.Blue)]
public enum Colors
{
    Red,
    Green,
    Blue
}

स्रोत:

public class SafeEnumConverter : StringEnumConverter
{
    private readonly int _defaultValue;

    public SafeEnumConverter()
    {
        // if you've been careful to *always* create enums with `0` reserved
        // as an unknown/default value (which you should), you could use 0 here. 
        _defaultValue = -1;
    }

    public SafeEnumConverter(int defaultValue)
    {
        _defaultValue = defaultValue;
    }

    /// <summary>
    /// Reads the provided JSON and attempts to convert using StringEnumConverter. If that fails set the value to the default value.
    /// </summary>
    /// <returns>The deserialized value of the enum if it exists or the default value if it does not.</returns>
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        try
        {
            return base.ReadJson(reader, objectType, existingValue, serializer);
        }
        catch
        {
            return Enum.Parse(objectType, $"{_defaultValue}");
        }
    }

    public override bool CanConvert(Type objectType)
    {
        return base.CanConvert(objectType) && objectType.GetTypeInfo().IsEnum;
    }
}

पृष्ठभूमि

जब हमने StringEnumConverterइस समस्या का उपयोग करके देखा , तो हमारे पास यह समस्या थी कि नए एनम वैल्यू को जोड़ने पर हमें उन मामलों के लिए भी निष्क्रियता की आवश्यकता थी, लेकिन हर ग्राहक को नए मूल्य के बारे में तुरंत जानकारी नहीं थी। इन मामलों में, StringEnumConverterNewtonsoft JSON के साथ पैक JsonSerializationException"EnumType टाइप करने के लिए मान SomeString" में एक समान त्रुटि फेंकता है और फिर पूरी deserialization प्रक्रिया विफल हो जाती है। यह हमारे लिए एक सौदा ब्रेकर था, क्योंकि भले ही ग्राहक उस संपत्ति के मूल्य को अनदेखा करने / त्यागने की योजना बना रहा हो जो उसे समझ में नहीं आया था, फिर भी उसे शेष पेलोड को निष्क्रिय करने में सक्षम होने की आवश्यकता थी!


-2
        Person p = new Person();
        p.Age = 35;
        p.Gender = Gender.Male;
        //1.  male="Male";
        string male = Gender.Male.ToString();

        p.Gender = Gender.Female;

        //2.  female="Female";
        string female = Enum.GetName(typeof(Gender), p.Gender);

        JObject jobj = new JObject();
        jobj["Age"] = p.Age;
        jobj["Gender"] = male;
        jobj["Gender2"] = female;

        //you result:  josn= {"Age": 35,"Gender": "Male","Gender2": "Female"}
        string json = jobj.ToString();

-5
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]  
);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.