ProgramingTip

JavaScriptSerializer Serializer JSON- 열거 형을 쉽게 만들 수 있습니다.

bestdevel 2020. 9. 27. 13:18
반응형

JavaScriptSerializer Serializer JSON- 열거 형을 쉽게 만들 수 있습니다.


enum속성 을 포함하는 클래스가 사용하여 개체를 구성 화하면 JavaScriptSerializerjson 결과에 string"이름"이 열거 형의 정수 값이 포함 됩니다. string사용자 정의를 만들지 않고 내 json에서 열거 형을 이용하는 방법이 JavaScriptConverter있습니까? enum정의 또는 속성을 장식 할 수있는 속성이 있습니까?

예로서 :

enum Gender { Male, Female }

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

원하는 json 결과 :

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

기본 제공 .NET 프레임 워크 클래스로 답변을 찾는 것이 있고, 가능하지 않은 경우 (예 : Json.net) 대안을 환영합니다.


사용할 수있는 특별한 속성이 없습니다. 문자열 표현이 아닌 숫자 값으로 JavaScriptSerializer문자열 화 enums합니다. enum숫자 값 대신 이름으로 숫자 값 대신 이름으로 배열 화 선택 합니다.


당신이 JSON.Net 대신 사용할 수있는 경우 JavaScriptSerializer에 비해 참조이 질문에 에서 제공 OmerBakhari : JSON.net이 사용 (속성을 통해 케이스 포함 [JsonConverter(typeof(StringEnumConverter))]) 및 .NET 시리얼에 내장 처리하지 많은 사람들을. 다음은 serializer의 기능을 비교하는 링크 입니다.


Json.NETStringEnumConverter속성으로 발견 된 정확한 기능을 제공 했습니다 .

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

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

자세한 내용은 StringEnumConverter설명서를 참조하십시오 .

이 변환기를 더 전역 적으로 구성 할 수 있습니다.

  • enum을 항상 발급로 낳음 / 역으로 낳음 enum 자체 :

    [JsonConverter(typeof(StringEnumConverter))]  
    enum Gender { Male, Female }
    
  • 누군가 속성 장식을 피하고 싶은 경우, 변환기를 JsonSerializer에 추가 할 수 있습니다 ( Bjørn Egil에서 제안 ).

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

    여기에 표시되는 모든 열거 형에 대해 작동합니다 ( Travis 제안 ).

  • 또는 JsonConverter ( banana에서 제안 ) :

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

또한 StringEnumConverter (의 NamingStrategy, 부울) 생성자 를 사용하여-to-/ 소문자 및 숫자 허용 여부를 제어 할 수 있습니다 .


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

@Iggy 대답은 C # 열거 형의 JSON 화를 ASP.NET (웹 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
}

@ob.의 최상위 답변과 같이 소스 모델을 설명 수 없었고 @Iggy처럼 전역 적으로 등록하고 싶지. 그래서 https://stackoverflow.com/a/2870420/237091 과 @Iggy의 https://stackoverflow.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()
        }
    })

Omer Bokhari와 uri의 답변의 조합은 항상 내 솔루션입니다. 제가 제공하는 값이 일반적으로 내가 enum에있는 값과 다르기 때문에 필요에 따라 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; }
}

쉽게 추가하여 이것은 이루어집니다 받는 속성 이 직렬화 할 수 없습니다 원인, 및 추가 특성 부동산 않습니다 직렬화 얻을를 :ScriptIgnoreGenderGenderString

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

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

이 버전의 Stephen의 답변 은 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; 
        }
    }
}

다음은 newtonsoft.json에 대한 답변입니다.

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

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

ASP.NET Core 방식 :

public class Startup
{
  public IServiceProvider ConfigureServices(IServiceCollection services)
  {
    services.AddMvc().AddJsonOptions(options =>
    {
      options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
    });
  }
}

https://gist.github.com/regisdiogo/27f62ef83a804668eb0d9d0f63989e3e


다음은 서버 측 C # 열거 형을 JSON으로 생성 화하고 결과를 사용하여 클라이언트 측 <select>요소 를 채우는 간단한 솔루션입니다 . 열거 된 열거 형과 비트 플래그 열거 형 모두에서 작동합니다.

C # 열거 형을 JSON으로 배열 화하려는 대부분의 사람들이 <select>드롭 다운 을 채우는데도 사용할 솔루션을 포함했습니다 .

여기에 간다 :

예제 열거 형

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

비트 OR를 사용하여 권한 시스템을 생성하는 복잡한 열거 형입니다. 그러나 열거 형의 정수 값에 대해 단순 등급 [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의 Response.AsJson()도우미를 사용 하지만 열거 형이 이미 메서드 화 준비가 된 간단한 익명 유형으로 젝션 검증 된 표준 JSON 형식으로 사용할 수 있습니다.

생성 된 JSON

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

클라이언트 측 -CoffeeScript

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>

속성 JsonSerializer을 사용하지 않는 경우 변환기를 추가 할 수도 있습니다 JsonConverter.

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

enum보는 중에 직렬화 모든 것에 대해 작동합니다 .


ASP.Net 코어의 경우 시작 클래스에 다음을 추가하십시오.

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

아래와 같이 JsonConverter.SerializeObject를 호출하여 JsonSerializerSettings를 만들 수 있습니다.

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

.Net Core의 경우 :-

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

설명 속성이있는 경우 화에 대한 응답이 없음을 확인했습니다.

다음은 설명 속성을 지원하는 구현입니다.

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

이것이 오래된 질문이지만 만약 대비하여 기여할 생각했습니다. 내 프로젝트에서는 Json 요청에 대해 별도의 모델을 사용합니다. 모델은 일반적으로 "Json"접두사가있는 도메인 개체와 이름이 있습니다. 모델은 AutoMapper를 사용하여 매핑 됩니다. json 모델이 도메인 클래스의 열거 형인 클래스 속성을 선언합니다 AutoMapper는 해당 클래스의 표현을 확인합니다.

궁금한 점이 있다는 점이 Json 클래스에 대해 별도의 모델이 필요합니다. 확장자 내장 변환기가 순환 참조를 제공하기 때문입니다.

이것이 누군가를 돕기를 바랍니다.


누구든지 위의 내용이 충분하지 않아서 생각하는 경우를 충분하지 않고 생각하는 경우 해결했습니다.

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

실제로 JavaScriptConverter를 사용하여 기본 제공 JavaScriptSerializer 로이를 수행 할 수 있습니다. 열거 형을 Uri로 변환하여 인코딩으로 인코딩 할 수 있습니다.

날짜에 대해 설명이 작업을 수행하는 방법을 설명했지만 열거 형에도 사용할 수 있습니다. .NET JavaScriptSerializer 용 사용자 지정 DateTime JSON 형식 .


이것이 여전히 관련이 있는지 확실하지 않지만 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 "규칙"에 따라 시작하는 소문자임을 확인합니다. 깔끔하게 들여 쓰기 된 형식을 지정하고 출력에서 ​​null을 무시합니다. 또한 StringEnumConverter를 추가하여 고급 값과 함께 열거를 인쇄합니다.

개인적으로 나는 주석으로 모델을 더럽 히지에서 내가 생각해 낼 수있는 가장 발견 된 것을 발견했습니다.

용법 :

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

Newtonsoft.Json라이브러리를 사용하여이 솔루션의 모든 부분을 모았습니다 . 열거 형 문제를 수정하고 오류 처리를 훨씬 개선하며 IIS 호스팅 서비스에서 작동합니다. 상당히 많은 코드이므로 GitHub ( https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs) 에서 찾을 수 있습니다.

Web.config작동하려면 몇 가지 항목을 추가해야 합니다. 여기에서 예제 파일을 볼 수 있습니다. https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config


그리고 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)

약간 더 미래 지향적 인 옵션

같은 질문에 직면하여 StringEnumConverter우리는 열거 형 값이 역 직렬화 측면에서 비극적으로 중단되지 않고 시간이 지남에 따라 확장 될 수 있도록 사용자 지정 버전이 필요하다고 결정했습니다 (아래 배경 참조). 은 Using SafeEnumConverter다음은 페이로드 가까이 INT - 투 - 열거 형 변환이 어떻게 작동하는지에 대한 명명 된 정의가없는 열거 값을 포함하더라도 끝까지 직렬화 할 수 있습니다.

용법:

[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문제는 새로운 enum 값이 추가 된 경우에도 수동성이 필요했지만 모든 클라이언트가 새 값을 즉시 인식하지는 못했다는 것입니다. 이러한 경우 StringEnumConverterNewtonsoft JSON과 함께 패키징 된 경우 JsonSerializationException"SomeString 값을 EnumType 유형으로 변환하는 동안 오류 발생"과 유사한 메시지가 표시되고 전체 역 직렬화 프로세스가 실패합니다. 클라이언트가 이해하지 못한 속성 값을 무시 / 삭제할 계획이더라도 나머지 페이로드를 역 직렬화 할 수 있어야했기 때문에 이것은 우리에게 거래 차단기였습니다!


.net core 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); 

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

참고 URL : https://stackoverflow.com/questions/2441290/javascriptserializer-json-serialization-of-enum-as-string

반응형