c# - تسلسل JSON التعداد كسلسلة



asp.net enums javascriptserializer (17)

لدي فئة تحتوي على خاصية enum ، وعند تسلسل الكائن باستخدام JavaScriptSerializer ، تحتوي النتيجة json على قيمة عدد صحيح من التعداد بدلاً من "اسم" string الخاصة به. هل هناك طريقة للحصول على التعداد string في json دون الحاجة إلى إنشاء JavaScriptConverter مخصص؟ ربما هناك سمة يمكن أن أقوم بتزيين تعريف enum ، أو خاصية الكائن ، مع؟

كمثال:

enum Gender { Male, Female }

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

نتيجة json المرغوب فيها:

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

Answers

لـ .Net Core Web Api: -

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

هذا سؤال قديم لكنني ظننت أنني سأشارك في القضية فقط. في مشاريعي أستخدم نماذج منفصلة لأي طلبات Json. عادة ما يكون للنموذج نفس الاسم ككائن المجال مع بادئة "Json". يتم تخطيط النماذج باستخدام AutoMapper . من خلال جعل نموذج json يعلن خاصية سلسلة تمثل تعدادًا على فئة المجال ، سيتم حل AutoMapper إلى عرض تقديمي لها.

في حال كنت أتساءل ، أحتاج إلى نماذج منفصلة لصفوف Json المتسلسلة لأن المشغل يحمل في ثناياه عوامل يأتي مع مراجع دائرية على خلاف ذلك.

أمل أن هذا يساعد شخصاما.


لم أتمكن من تغيير نموذج المصدر كما في الإجابة الأعلى (ob.) ، ولم أكن أرغب في تسجيله عالميًا مثلIggy. لذلك جمعت https://.com/a/2870420/237091 و @ Iggy https://.com/a/18152942/237091 للسماح بإعداد المحول التعدادية للسلسلة أثناء أمر SerializeObject نفسه:

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

أضف أدناه إلى global.asax الخاص بك لتسلسل JSON لـ c # enum كسلسلة

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

            config.Formatters.JsonFormatter.SerializerSettings.Converters.Add
                (new Newtonsoft.Json.Converters.StringEnumConverter());

هذا هو الحل البسيط الذي يقوم بتسلسل التعداد C # من جانب الخادم إلى JSON ويستخدم النتيجة لملء عنصر <select> جانب العميل. يعمل هذا لكل من التعدادات البسيطة وتعدادات bitflag.

لقد قمت بتضمين الحل المتكامل لأنني أعتقد أن معظم الأشخاص الراغبين في تسلسل C # enum إلى JSON ربما يستخدمونه أيضًا لملء قائمة <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);
};

يستخدم الكود أعلاه إطار عمل NancyFX للتعامل مع طلب الحصول على. ويستخدم أسلوب مساعد Nancy's Response.AsJson() - ولكن لا تقلق ، يمكنك استخدام أي من منسق JSON القياسي حيث تم طرح التعداد بالفعل في نوع مجهول بسيط جاهز للتسلسل.

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>

فقط في حال وجد أي شخص غير كافٍ أعلاه ، انتهى بي الأمر بالاستقرار مع هذا الحمل الزائد:

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

يمكنك إنشاء JsonSerializerSettings مع المكالمة إلى JsonConverter.SerializeObject على النحو التالي:

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

يتم ذلك بسهولة عن طريق إضافة سمة ScriptIgnore إلى الخاصية Gender ، مما يؤدي إلى عدم إجراء تسلسل لها ، وإضافة خاصية GenderString التي يتم تسلسلها:

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

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

هنا هو الجواب ل newtonsoft.json

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

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

Iggy تحدد مجموعات JSON تسلسل c # enum كسلسلة فقط لـ ASP.NET (Web API وهكذا).

ولكن لجعلها تعمل أيضًا مع التسلسل المخصص ، أضف المتابعة لفئة البداية (مثل 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

بالإضافة إلى ذلك ، لجعل عضو التعداد الخاص بك لإجراء تسلسل / إلغاء تسلسل إلى / من نص محدد ، استخدم

System.Runtime.Serialization.EnumMember

سمة ، مثل هذا:

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

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

لاحظت عدم وجود إجابة للتسلسل عند وجود سمة الوصف.

هنا هو التنفيذ الذي يدعم السمة الوصف.

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

التعداد:

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

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

يمكنك أيضًا إضافة محول إلى JsonSerializer إذا كنت لا ترغب في استخدام سمة JsonConverter :

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

سوف يعمل مع كل enum الذي يراه أثناء التسلسل.


لا يوجد سمة خاصة يمكنك استخدامها. JavaScriptSerializer تسلسل enums إلى قيمها الرقمية وليس تمثيل السلسلة الخاصة بهم. ستحتاج إلى استخدام التسلسل المخصص لإجراء تسلسل enum بدلاً من قيمة رقمية.

تحرير: كما أشار إليهاOmerBakhari JSON.net يغطي حالة الاستخدام هذه (عبر السمة [JsonConverter(typeof(StringEnumConverter))] وغيرها الكثير غير المتداولة من خلال المسلسلات المدمجة في .net. هنا هو رابط يقارن بين الميزات والوظائف من المسلسلات .


لقد وجدت أن Json.NET يوفر الوظيفة الدقيقة التي أبحث عنها مع سمة StringEnumConverter :

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

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

مزيد من التفاصيل متوفرة على وثائق StringEnumConverter .


يمكنك في الواقع استخدام JavaScriptConverter لإنجاز ذلك باستخدام JavaScriptSerializer المدمج. عن طريق تحويل التعداد إلى أوري يمكنك ترميزه كسلسلة.

لقد وصفت كيفية القيام بذلك للتواريخ ولكن يمكن استخدامها للتعداد كذلك.

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


Simplest solution:

خلق

var Status = Object.freeze({
    "Connecting":0,
    "Ready":1,
    "Loading":2,
    "Processing": 3
});

Get Value

console.log(Status.Ready) // 1

Get Key

console.log(Object.keys(Status)[Status.Ready]) // Ready




c# asp.net json enums javascriptserializer