programing

열거를 문자열로 직렬화

linuxpc 2023. 4. 6. 21:11
반응형

열거를 문자열로 직렬화

일람표가 있습니다.

public enum Action {
    Remove=1,
    Add=2
}

그리고 수업:

[DataContract]
public class Container {
    [DataMember]
    public Action Action {get; set;}
}

용기의 인스턴스를 직렬화하는 경우 이 테 스 렬 턴 음 화 표 시 serial when됩니다같이:son j다son containerize of i컨으면과하인직{Action:1}(일 경우)이 제거됩니다.(작업 remove경 (

I would like to get: 다음을 원합니다.{Action:Remove}(예: 열거된 ) 열거)에 대한 문자열 형식을 지정해야 합니다.

다른 멤버 추가 없이 할 수 있나요?

Json 사용.Net, 커스텀을 정의할 수 있습니다.StringEnumConverter as ~하듯이

public class MyStringEnumConverter : Newtonsoft.Json.Converters.StringEnumConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value is Action)
        {
            writer.WriteValue(Enum.GetName(typeof(Action),(Action)value));// or something else
            return;
        }

        base.WriteJson(writer, value, serializer);
    }
}

로서 연재하다

string json=JsonConvert.SerializeObject(container,new MyStringEnumConverter());

애트리뷰트를 추가할 수 있습니다.

    [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))] 

문자열로 일련화되지 않은 열거 속성으로 이동합니다.

또는 보다 이국적인 포맷을 염두에 두고 있는 경우 다음과 같은 Atribut을 사용하여 JSON serializer에 원하는 대로 포맷한 속성만 시리얼화하도록 지시할 수 있습니다.나머지 구현에 따라 다릅니다.또한 속성의 DataMember 속성도 인식합니다.

[JsonObject(MemberSerialization = MemberSerialization.OptOut)]
public class Container
{
    public Action Action { get; set; }

    [JsonProperty(PropertyName = "Action")]
    public string ActionString
    {
        get
        {
            return Action.ToString();
        }
    }
}

JSON 포메터는 열거를 사용할 때 매우 특수한 동작을 합니다. 일반 데이터 계약 속성은 무시되고 열거를 다른 형식에서 더 쉽게 읽을 수 있는 문자열이 아닌 숫자로 취급합니다.이렇게 하면 플래그 유형의 열거를 쉽게 처리할 수 있지만 대부분의 다른 유형의 작업은 훨씬 더 어려워집니다.

MSDN에서:

열거 멤버 값은 JSON에서 숫자로 처리되며, 이는 멤버 이름으로 포함되는 데이터 계약에서 처리되는 방법과 다릅니다.데이터 계약 처리에 대한 자세한 내용은 데이터 계약의 열거 유형을 참조하십시오.

  • 를 들어, 「」가 있는 는,public enum Color {red, green, blue, yellow, pink}노란색을 시리얼화하면 숫자 3이 생성되고 문자열 "yellow"가 생성되지 않습니다.

  • 모든 열거형 구성원은 직렬화할 수 있습니다.EnumMemberAttribute 및 NonSerializedAttribute Atribute Atribute Atribute를 사용할 경우 무시됩니다.

  • 존재하지 않는 열거형 값을 역직렬화할 수 있습니다.예를 들어, 대응하는 색상 이름이 정의되어 있지 않은 경우에도 값 87을 이전 색상 열거형으로 역직렬화할 수 있습니다.

  • flags 열거형은 특별하지 않으며 다른 열거형과 동일하게 취급됩니다.

이 문제를 해결하는 유일한 실용적인 방법은 최종 사용자가 숫자 대신 문자열을 지정할 수 있도록 계약에서 열거형을 사용하지 않는 것입니다.대신 실제 답변은 열거형을 문자열로 대체하고 값을 유효한 열거형 표현 중 하나로 구문 분석할 수 있도록 내부 검증을 수행하는 것입니다.

또는 (마음의 척이 아닌) JSON 포메터를 자신의 포메터로 대체할 수도 있습니다.이 포메터는 다른 포메터와 마찬가지로 열거를 존중합니다.

간단한 방법은 다음과 같습니다.

JsonConvert.SerializeObject(myObject, Formatting.Indented, new StringEnumConverter());

과 serialization의 serialization에 name 또는 serialization의 이러한 속성은 열거 멤버 이름 또는 값에서 시리얼라이제이션에 사용됩니다.EnumMemberAttribute.

가장 큰 장점은 다음과 같습니다.

  • 시리얼라이저를 사용하여 조정할 필요가 없습니다.
  • 모든 시리얼라이제이션 로직이 데이터 오브젝트에 포함됩니다.
  • 보조 속성은 DataContractSerializer가 개인 속성을 가져오고 설정할 수 있으므로 보조 속성을 개인으로 설정하여 숨길 수 있습니다.
  • 은 '연재하다'로할 수 .string int

클래스는 다음과 같습니다.

[DataContract]
public class SerializableClass {
    public Shapes Shape {get; set;} //Do not use the DataMemberAttribute in the public property

    [DataMember(Name = "shape")]
    private string ShapeSerialization // Notice the PRIVATE here!
    {
        get { return EnumHelper.Serialize(this.Shape); }
        set { this.Shape = EnumHelper.Deserialize<Shapes>(value); }
    }
}

EnumHelper.cs

/* Available at: https://gist.github.com/mniak/a4d09264ad1ca40c489178325b98935b */
public static class EnumHelper
{
    public static string Serialize<TEnum>(TEnum value)
    {
        var fallback = Enum.GetName(typeof(TEnum), value);
        var member = typeof(TEnum).GetMember(value.ToString()).FirstOrDefault();
        if (member == null)
            return fallback;
        var enumMemberAttributes = member.GetCustomAttributes(typeof(EnumMemberAttribute), false).Cast<EnumMemberAttribute>().FirstOrDefault();
        if (enumMemberAttributes == null)
            return fallback;
        return enumMemberAttributes.Value;
    }
    public static TEnum Deserialize<TEnum>(string value) where TEnum : struct
    {
        TEnum parsed;
        if (Enum.TryParse<TEnum>(value, out parsed))
            return parsed;

        var found = typeof(TEnum).GetMembers()
            .Select(x => new
            {
                Member = x,
                Attribute = x.GetCustomAttributes(typeof(EnumMemberAttribute), false).OfType<EnumMemberAttribute>().FirstOrDefault()
            })
            .FirstOrDefault(x => x.Attribute?.Value == value);
        if (found != null)
            return (TEnum)Enum.Parse(typeof(TEnum), found.Member.Name);
        return default(TEnum);
    }
}

Michal B가 게시한 솔루션은 효과가 있습니다.여기 다른 예가 있어.

Description Attribute는 시리얼화할 수 없으므로 다음을 수행해야 합니다.

[DataContract]
public enum ControlSelectionType
{
    [EnumMember(Value = "Not Applicable")]
    NotApplicable = 1,
    [EnumMember(Value = "Single Select Radio Buttons")]
    SingleSelectRadioButtons = 2,
    [EnumMember(Value = "Completely Different Display Text")]
    SingleSelectDropDownList = 3,
}


public static string GetDescriptionFromEnumValue(Enum value)
{
    EnumMemberAttribute attribute = value.GetType()
        .GetField(value.ToString())
        .GetCustomAttributes(typeof(EnumMemberAttribute), false)
        .SingleOrDefault() as EnumMemberAttribute;
    return attribute == null ? value.ToString() : attribute.Value;}

를 사용하고 있는 경우.native json 시리얼라이저(즉,시스템.텍스트, Json.시리얼라이제이션에서는 열거형을 int가 아닌 문자열로 변환하도록 열거형에 속성을 추가할 수 있습니다.

문자열로 사용할 열거형에 다음 특성을 추가해야 합니다.

[Json Converter (type of (Json String Enum Converter)]

사용해보십시오.

public enum Action {
    [EnumMember(Value = "Remove")]
    Remove=1,
    [EnumMember(Value = "Add")]
    Add=2
}

하지만 이것이 당신의 경우에 적합한지 잘 모르기 때문에 제가 틀릴 수도 있습니다.

자세한 것은, http://msdn.microsoft.com/en-us/library/aa347875.aspx 를 참조해 주세요.

직렬화를 위해 컨테이너에 열거 속성이 포함되지 않아야 하지만 채워진 경우 아래 확장 메서드를 사용할 수 있습니다.

컨테이너 정의

public class Container
{
    public string Action { get; set; }
}

열거 정의

public enum Action {
    Remove=1,
    Add=2
}

뷰의 코드

@Html.DropDownListFor(model => model.Action, typeof (Action))

확장 방식

/// <summary>
/// Returns an HTML select element for each property in the object that is represented by the specified expression using the given enumeration list items.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TProperty">The type of the value.</typeparam>
/// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
/// <param name="expression">An expression that identifies the object that contains the properties to display.</param>
/// <param name="enumType">The type of the enum that fills the drop box list.</param>
/// <returns>An HTML select element for each property in the object that is represented by the expression.</returns>
public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression, Type enumType)
{
    var values = from Enum e in Enum.GetValues(enumType)
                    select new { Id = e, Name = e.ToString() };

    return htmlHelper.DropDownListFor(expression, new SelectList(values, "Id", "Name"));
}

이 문제를 해결하기 위해Newtonsoft.Json 에 의해, 한층 또, 서비스가 아닌 합니다.열거형 문제를 수정하고 오류 처리도 훨씬 개선하며 자체 호스팅된 서비스가 아닌 IIS 호스팅된 서비스에서 작동합니다. 바꿀 , .DataContract반.꽤 많은 코드이기 때문에 GitHub에서 찾을 수 있습니다.https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs

엔트리를 몇 개 추가해야 합니다.Web.config이 기능을 이용하려면 , 다음의 샘플 파일을 참조해 주세요.https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config

언급URL : https://stackoverflow.com/questions/9156820/serialize-enum-to-string

반응형