1305

プロパティを含むクラスがあり、enumを使用してオブジェクトをシリアル化すると、json の結果には「名前」JavaScriptSerializerではなく列挙の整数値が含まれます。カスタムを作成せずに、json でstringenum を取得する方法はありますか? おそらく、定義またはオブジェクト プロパティを装飾できる属性があるでしょうか?stringJavaScriptConverterenum

例として:

enum Gender { Male, Female }

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

望ましい JSON 結果:

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

理想的には、組み込みの .NET フレームワーク クラスを使用して回答を探します。可能でない場合は、代替手段 (Json.net など) を歓迎します。

4

29 に答える 29

2265

Json.NETが、私が探している正確な機能をStringEnumConverter属性で提供することがわかりました。

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 (バナナが推奨):

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

さらに、StringEnumConverter(NamingStrategy, Boolean)コンストラクターを使用して、大文字と小文字を制御し、数値を引き続き受け入れるかどうかを制御できます。

于 2010-05-20T00:58:33.230 に答える
450

いいえ、使用できる特別な属性はありません。文字列表現ではなく、数値にJavaScriptSerializerシリアル化します。を数値ではなく名前としてenumsシリアル化するには、カスタム シリアル化を使用する必要があります。enum


OmerBakhariが提供するこの質問の回答をJavaScriptSerializer参照 する代わりに、JSON.Net を使用できる場合: JSON.net は、このユースケース (属性を介して) と、組み込みの .net シリアライザーでは処理されない他の多くのケースをカバーしています。これは、シリアライザーの特徴と機能を比較するリンクです[JsonConverter(typeof(StringEnumConverter))]

于 2010-03-14T06:21:10.860 に答える
180

以下を global.asax に追加して、c# enum を文字列として JSON シリアル化します。

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

            config.Formatters.JsonFormatter.SerializerSettings.Converters.Add
                (new Newtonsoft.Json.Converters.StringEnumConverter());
于 2013-08-09T18:06:33.353 に答える
31

これは、プロパティにScriptIgnore属性を追加してシリアル化しないようにし、シリアル化されるプロパティを追加することで簡単に実行できます。GenderGenderString

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

    string GenderString { get { return Gender.ToString(); } }
}
于 2012-03-15T17:38:34.723 に答える
27

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; 
        }
    }
}
于 2012-04-26T13:55:37.653 に答える
25

これがnewtonsoft.jsonの答えです

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}
于 2015-04-21T09:47:56.430 に答える
22

System.Text.Json を使用した Asp.Net Core 3

public void ConfigureServices(IServiceCollection services)
{

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

    //...
 }
于 2019-11-11T00:31:52.673 に答える
19

属性JsonSerializerを使用したくない場合は、コンバーターを追加することもできます。JsonConverter

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

enumそのシリアル化中に表示されるすべてに対して機能します。

于 2016-04-05T11:15:39.807 に答える
16

これは、サーバー側の C# 列挙型を JSON にシリアル化し、その結果を使用してクライアント側の<select>要素を設定する単純なソリューションです。これは、単純な列挙型とビットフラグ列挙型の両方で機能します。

<select>C# 列挙型を JSON にシリアライズしたいと考えているほとんどの人は、おそらくそれを使用してドロップダウンを埋めていると思うので、エンド ツー エンド ソリューションを含めました。

ここに行きます:

列挙型の例

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>
于 2013-04-10T10:06:43.220 に答える
16

ASP.Net コアの場合、スタートアップ クラスに以下を追加するだけです。

JsonConvert.DefaultSettings = (() =>
        {
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new StringEnumConverter { AllowIntegerValues = false });
            return settings;
        });
于 2018-10-17T05:49:14.043 に答える
13

以下のように、JsonConverter.SerializeObject を呼び出して JsonSerializerSettings を作成できます。

var result = JsonConvert.SerializeObject
            (
                dataObject,
                new JsonSerializerSettings
                {
                    Converters = new [] {new StringEnumConverter()}
                }
            );
于 2015-06-17T12:29:49.097 に答える
12

Description 属性がある場合、シリアル化の答えがないことに注意してください。

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; }
于 2016-03-05T08:29:03.173 に答える
8

誰かが上記のものが不十分だと思った場合に備えて、私はこのオーバーロードで解決しました:

JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter())
于 2016-06-27T08:35:49.150 に答える
5

これは古い質問ですが、念のため貢献したいと思いました。私のプロジェクトでは、Json リクエストごとに個別のモデルを使用しています。モデルは通常、「Json」プレフィックスが付いたドメイン オブジェクトと同じ名前になります。モデルはAutoMapperを使用してマップされます。json モデルでドメイン クラスの列挙型である文字列プロパティを宣言することにより、AutoMapper はその文字列表現に解決されます。

ご参考までに、Json のシリアル化されたクラスには個別のモデルが必要です。それ以外の場合は、組み込みのシリアライザーが循環参照を作成するためです。

これが誰かに役立つことを願っています。

于 2012-03-27T15:58:04.007 に答える
3

実際に JavaScriptConverter を使用して、組み込みの JavaScriptSerializer でこれを実現できます。列挙型を Uri に変換することで、それを文字列としてエンコードできます。

日付に対してこれを行う方法を説明しましたが、列挙型にも使用できます。 .NET JavaScriptSerializer のカスタム DateTime JSON 形式

于 2011-12-28T10:29:30.070 に答える