etc./StackOverFlow

JavaScriptSerializer - 열거형을 문자열로 JSON 직렬화

청렴결백한 만능 재주꾼 2023. 4. 28. 04:05
반응형

질문자 :Omer Bokhari


enum 속성이 포함된 클래스가 있고 JavaScriptSerializer 사용하여 개체를 직렬화하면 string "name"이 아닌 열거형의 정수 값이 포함됩니다. JavaScriptConverter 를 만들지 않고도 string 로 가져오는 방법이 있습니까? enum 정의 또는 개체 속성을 장식할 수 있는 속성이 있습니까?

예로서:

 enum Gender { Male, Female } class Person { int Age { get; set; } Gender Gender { get; set; } }

원하는 json 결과:

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

가능한 대안(예: Json.net)이 있는 경우 기본 제공 .NET 프레임워크 클래스로 답변을 찾는 것이 이상적입니다.



Json.NET StringEnumConverter 속성으로 내가 찾고 있는 정확한 기능을 제공한다는 것을 발견했습니다.

 using Newtonsoft.Json; using Newtonsoft.Json.Converters; [JsonConverter(typeof(StringEnumConverter))] public Gender Gender { get; set; }

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

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

  • 열거형을 항상 문자열로 직렬화/역직렬화하려는 경우 열거형 자체:

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

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

    그리고 직렬화(Travis 제안) 중에 보는 모든 열거형에 대해 작동합니다.

  • 또는 JsonConverter( 바나나 제안):

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

또한 StringEnumConverter(NamingStrategy, Boolean) 생성자를 사용하여 대소문자와 숫자가 계속 허용되는지 여부를 제어할 수 있습니다.


Omer Bokhari

아니요 사용할 수 있는 특별한 속성이 없습니다. JavaScriptSerializer enums 을 문자열 표현이 아닌 숫자 값으로 직렬화합니다. enum 을 숫자 값 대신 이름으로 직렬화하려면 사용자 정의 직렬화를 사용해야 합니다.


JavaScriptSerializer 대신 JSON.Net을 사용할 수 있다면 OmerBakhari에서 제공하는 이 질문에 대한 답변을 참조하세요 . JSON.net은 이 사용 사례를 다룹니다( [JsonConverter(typeof(StringEnumConverter))] .net 직렬 변환기.다음은 직렬 변환기의 기능을 비교하는 링크 입니다.


Matt Dearing

C# 열거형을 문자열로 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

@Iggy 답변은 C# enum의 JSON 직렬화를 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 }

Juri

@ob.의 최상위 답변과 같이 소스 모델을 변경할 수 없었고 @Iggy처럼 전역적으로 등록하고 싶지 않았습니다. 그래서 SerializeObject 명령 자체 중에 문자열 열거형 변환기를 설정할 수 있도록 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() } })

Scott Stafford

Omer Bokhari 와 uri 의 답변 조합은 항상 내 솔루션입니다. 제공하려는 값은 일반적으로 내가 필요로 하는 경우 열거형을 변경할 수 있기를 원하는 열거형에 있는 것과 다르기 때문입니다.

따라서 관심이 있는 사람이 있으면 다음과 같습니다.

 public enum Gender { [EnumMember(Value = "male")] Male, [EnumMember(Value = "female")] Female } class Person { int Age { get; set; } [JsonConverter(typeof(StringEnumConverter))] Gender Gender { get; set; } }

Ashkan Sirous

.net core 3에서는 이제 System.Text.Json의 기본 제공 클래스를 사용하여 이것이 가능합니다( 편집 : System.Text.Json은 .net core 2.0 및 .net 프레임워크 4.7.2 이상용 NuGet 패키지로도 사용할 수 있습니다. 문서 에 따른 버전 ):

 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 }

Björn

이것은 쉽게 추가하여 수행됩니다 ScriptIgnore 받는 사람 속성을 Gender 은 직렬화 할 수 없습니다 원인, 특성 및 추가 GenderString 직렬화됩니까 속성을 :

 class Person { int Age { get; set; } [ScriptIgnore] Gender Gender { get; set; } string GenderString { get { return Gender.ToString(); } } }

Stephen Kennedy

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


st1

이 버전의 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; } } }

mheyman

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

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

GuCa

System.Text.Json이 포함된 Asp.Net Core 3

 public void ConfigureServices(IServiceCollection services) { services .AddControllers() .AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()) ); //... }

Serj-Tm

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

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

해당 직렬화 중에 표시되는 enum 대해 작동합니다.


GorvGoyl

다음은 서버 측 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 프레임워크를 사용하여 Get 요청을 처리합니다. 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>

biofractal

ASP.Net 코어의 경우 시작 클래스에 다음을 추가하기만 하면 됩니다.

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

Yahya Hussein

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

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

Yang Zhang

Description 속성이 있을 때 직렬화에 대한 응답이 없음을 확인했습니다.

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

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

Greg R Taylor

.Net Core의 경우 :-

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

PeteGO

누군가가 위의 내용이 충분하지 않다고 생각하는 경우를 대비하여 이 과부하로 해결했습니다.

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

hngr18

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

궁금한 경우 내장 직렬 변환기가 순환 참조를 제공하기 때문에 Json 직렬화 클래스에 대해 별도의 모델이 필요합니다.

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


Ales Potocnik Hahonina

실제로 JavaScriptConverter를 사용하여 내장 JavaScriptSerializer로 이를 수행할 수 있습니다. 열거형을 Uri로 변환하여 문자열로 인코딩할 수 있습니다.

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


Sebastian Markbåge

약간 더 미래 지향적인 옵션

동일한 질문에 직면하여 우리는 열거형 값이 역직렬화 측면에서 치명적으로 손상되지 않고 시간이 지남에 따라 확장될 수 있도록 하기 위해 StringEnumConverter 의 사용자 지정 버전이 필요하다고 결정했습니다(아래 배경 참조). 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 를 사용할 때 문제는 새 enum 값이 추가되었지만 모든 클라이언트가 새 값을 즉시 인식하지 못하는 경우에도 수동성이 필요했다는 것입니다. 이 경우, StringEnumConverter Newtonsoft JSON과 함께 패키지는 발생 JsonSerializationException 다음 전체 직렬화 프로세스가 실패 "오류가 EnumType를 입력 값 SomeString 변환"과 유사합니다. 클라이언트가 이해하지 못하는 속성 값을 무시/폐기로 계획했더라도 나머지 페이로드를 역직렬화할 수 있어야 했기 때문에 이것은 우리에게 거래 차단기였습니다!


Dusty

이것이 여전히 관련이 있는지 확실하지 않지만 json 파일에 직접 작성해야 했으며 몇 가지 stackoverflow 답변을 함께 연결하여 다음과 같은 결과를 도출했습니다.

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

kenny

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

Benjamin Swedlove

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

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


Jon Grant

이것을 사용하십시오:

 using Newtonsoft.Json; using Newtonsoft.Json.Converters; [Serializable] [JsonConverter(typeof(StringEnumConverter))] public enum Gender { Male, Female }

Андрей Петрашевич

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

zilong

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

Slava

출처 : http:www.stackoverflow.com/questions/2441290/javascriptserializer-json-serialization-of-enum-as-string

반응형