32 votes

ASP.NET MVC: Contrôle de la sérialisation des noms de propriété avec JsonResult

Est-il un moyen pour contrôler la sortie JSON de JsonResult avec des attributs, semblable à la façon dont vous pouvez utiliser XmlElementAttribute et de ses frères pour contrôler la sortie de la sérialisation XML?

Par exemple, pour la classe suivante:

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

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

J'aimerais pour ensuite obtenir la sortie suivante:

{ bar: '', oygevalt: '' }

Par opposition à:

{ Bar: '', Oygevalt: '' }

37voto

Daniel Schaffer Points 14707

Je voulais quelque chose d'un peu plus cuit dans le cadre de ce que Jarrett a suggéré, voici donc ce que j'ai fait:

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() la méthode, ajouté à ma classe de contrôleur de base:

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

Exemple D'Utilisation:

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

        return JsonContract(advertiser);
    }

Remarque: Si vous êtes à la recherche de quelque chose de plus performant que JsonDataContractSerializer, vous pouvez faire la même chose à l'aide de JSON.NET au lieu de cela. Alors que JSON.NET ne semble pas utiliser DataMemberAttribute, il possède son propre JsonPropertyAttribute qui peut être utilisé pour accomplir la même chose.

16voto

Charlie Kilian Points 3469

Voici ma mise en œuvre de Daniel Schaffer réponse, avec les améliorations suggérées par Justin Rusbatch et Daniel incorporated.

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

7voto

Daniel Points 825

C'est la solution à utiliser NewtonSoft Json.Net (pour la performance) J'ai trouvé une partie de la solution ici, et SI

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

De sorte que, dans mon contrôleur, je peux le faire

        return new JsonNetResult(result);

Dans mon modèle, je peux maintenant avoir:

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

Notez que maintenant, vous devez définir l' JsonPropertyAttribute de tous les biens que vous souhaitez pour sérialiser.

5voto

Danny Pérez Points 95

Je sais que c'est une vieille question, mais pour ceux qui sont à la recherche pour juste comment éviter les propriétés d'être sérialisé utiliser le ScriptIgnoreAttribute dans l'espace de noms System.Web.Script.La sérialisation. Malheureusement toujours pas controler le nom de la sérialisé propriétés, mais quelqu'un pourrait trouver cela utile.

public class MyClass {

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

    public bool AnyProperty { get; set; }
}

Sortie Json conséquence, le suivant:

{"AnyProperty ": false}

1voto

Nate Kohari Points 1748

La réponse est facile: l' DataContractJsonSerializer doit respecter l' [DataContract] et [DataMember] d'attributs dans le Système.Moment de l'exécution.La sérialisation de l'espace de noms de la BCL.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X