web-dev-qa-db-ja.com

ASP.NET MVC:JsonResultを使用したプロパティ名のシリアル化の制御

JsonResultとそのbretherenを使用してXMLシリアル化の出力を制御する方法と同様に、属性を使用してXmlElementAttributeのJSON出力を制御する方法はありますか?

たとえば、次のクラスがあるとします。

public class Foo
{
    [SomeJsonSerializationAttribute("bar")]
    public String Bar { get; set; }

    [SomeJsonSerializationAttribute("oygevalt")]
    public String Oygevalt { get; set; }
}

次に、次の出力を取得したいと思います。

{ bar: '', oygevalt: '' }

とは対照的に:

{ Bar: '', Oygevalt: '' }
31
Daniel Schaffer

Jarrettが提案したものよりもフレームワークに少し焼き付けたものが欲しかったので、次のようにしました。

JsonDataContractActionResult:

public class JsonDataContractActionResult : ActionResult
{
    public JsonDataContractActionResult(Object data)
    {
        this.Data = data;
    }

    public Object Data { get; private set; }

    public override void ExecuteResult(ControllerContext context)
    {
        var serializer = new DataContractJsonSerializer(this.Data.GetType());
        String output = String.Empty;
        using (var ms = new MemoryStream())
        {
            serializer.WriteObject(ms, this.Data);
            output = Encoding.Default.GetString(ms.ToArray());
        }
        context.HttpContext.Response.ContentType = "application/json";
        context.HttpContext.Response.Write(output);
    }
}

JsonContract()メソッド、基本コントローラークラスに追加:

    public ActionResult JsonContract(Object data)
    {
        return new JsonDataContractActionResult(data);
    }

使用例:

    public ActionResult Update(String id, [Bind(Exclude="Id")] Advertiser advertiser)
    {
        Int32 advertiserId;
        if (Int32.TryParse(id, out advertiserId))
        {
            // update
        }
        else
        {
            // insert
        }

        return JsonContract(advertiser);
    }

注: JsonDataContractSerializerよりもパフォーマンスの高いものを探している場合は、代わりにJSON.NETを使用して同じことを行うことができます。 JSON.NETはDataMemberAttributeを利用しているようには見えませんが、同じことを実現するために使用できる独自のJsonPropertyAttributeがあります。

38
Daniel Schaffer

これがダニエル・シャファーの答えの私の実装であり、ジャスティン・ラスバッチとダニエルによる提案された改善が組み込まれています。

using System;
using System.Runtime.Serialization.Json;
using System.Web.Mvc;

public class JsonDataContractActionResult : JsonResult
{
    public JsonDataContractActionResult( Object data )
    {
        this.Data = data;
    }

    public override void ExecuteResult( ControllerContext context )
    {
        var serializer = new DataContractJsonSerializer( this.Data.GetType() );
        context.HttpContext.Response.ContentType = "application/json";
        serializer.WriteObject( context.HttpContext.Response.OutputStream, 
            this.Data );
    }
}
16
Charlie Kilian

これは古い質問ですが、プロパティがシリアル化されないようにする方法を探している人は、名前空間System.Web.Script.Serializationで ScriptIgnoreAttribute を使用してください。残念ながら、シリアル化されたプロパティの名前を制御することはできませんが、誰かがこれが役立つと思うかもしれません。

public class MyClass {

    [ScriptIgnoreAttribute]
    public bool PropertyNotSerialized { get; set; }

    public bool AnyProperty { get; set; }
}

Jsonの結果として次のように出力されます。

{"AnyProperty ": false}
5
Danny Pérez

これは、NewtonSoft Json.Netを使用するためのソリューションです(パフォーマンスのために)私はソリューションの一部を見つけました ここ そしてSOで

public class JsonNetResult : ActionResult
    {
        public Encoding ContentEncoding { get; set; }
        public string ContentType { get; set; }
        public object Data { get; set; }

        public JsonSerializerSettings SerializerSettings { get; set; }
        public Formatting Formatting { get; set; }

        public JsonNetResult(object data, Formatting formatting)
            : this(data)
        {
            Formatting = formatting;
        }

        public JsonNetResult(object data):this()
        {
            Data = data;
        }

        public JsonNetResult()
        {
            Formatting = Formatting.None;
            SerializerSettings = new JsonSerializerSettings();
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");
            var response = context.HttpContext.Response;
            response.ContentType = !string.IsNullOrEmpty(ContentType)
              ? ContentType
              : "application/json";
            if (ContentEncoding != null)
                response.ContentEncoding = ContentEncoding;

            if (Data == null) return;

            var writer = new JsonTextWriter(response.Output) { Formatting = Formatting };
            var serializer = JsonSerializer.Create(SerializerSettings);
            serializer.Serialize(writer, Data);
            writer.Flush();
        }
    }

私のコントローラーでそれができるように

        return new JsonNetResult(result);

私のモデルでは、次のことができます。

    [JsonProperty(PropertyName = "n")]
    public string Name { get; set; }

ここで、シリアル化するすべてのプロパティにJsonPropertyAttributeを設定する必要があることに注意してください。

4
Daniel

簡単な答え:DataContractJsonSerializerは、BCLのSystem.Runtime.Serialization名前空間の[DataContract]属性と[DataMember]属性を尊重する必要があります。

1
Nate Kohari