ASP.NET MVC: управление сериализацией имен свойств с помощью JsonResult
Есть ли способ контролировать вывод JSON JsonResult
с атрибутами, похожими на то, как вы можете использовать XmlElementAttribute
и его контроль над выводом сериализации XML?
Например, дан следующий класс:
public class Foo
{
[SomeJsonSerializationAttribute("bar")]
public String Bar { get; set; }
[SomeJsonSerializationAttribute("oygevalt")]
public String Oygevalt { get; set; }
}
Я хотел бы получить следующий вывод:
{ bar: '', oygevalt: '' }
В отличие от:
{ Bar: '', Oygevalt: '' }
5 ответов
Я хотел что-то более запеченное в рамках, чем предлагал Джарретт, так что вот что я сделал:
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, который можно использовать для достижения той же цели.
Вот моя реализация ответа Дэниела Шаффера, с предложенными улучшениями Джастина Русбэтча и Дэниела.
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 );
}
}
Это решение использовать 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
для каждого свойства, которое вы хотите сериализовать.
Я знаю, что это старый вопрос, но для тех, кто ищет только то, как избежать сериализации свойств, используйте ScriptIgnoreAttribute в пространстве имен System.Web.Script.Serialization. К сожалению, все еще не может контролировать имя сериализованных свойств, но кто-то может найти это полезным.
public class MyClass {
[ScriptIgnoreAttribute]
public bool PropertyNotSerialized { get; set; }
public bool AnyProperty { get; set; }
}
Будет выводить как Json результат следующее:
{"AnyProperty ": false}
Простой ответ: DataContractJsonSerializer
должен уважать [DataContract]
а также [DataMember]
атрибуты в пространстве имен System.Runtime.Serialization в BCL.
Эти ответы были мне полезны, но, подойдя к этой проблеме на несколько лет позже, чем все остальные, я обнаружил, что этот код не работает с текущей версией фреймворка. Эта версия работает с Newtonsoft.Json и ASP NET Core 3.1:
/*
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
*/
public class JsonDataContractActionResult : IActionResult
{
public JsonDataContractActionResult(object data)
{
this.Data = data;
}
public object Data { get; private set; }
public async Task ExecuteResultAsync(ActionContext context)
{
context.HttpContext.Response.ContentType = "application/json";
JsonSerializer serializer = new JsonSerializer();
serializer.NullValueHandling = NullValueHandling.Ignore;
using (MemoryStream ms = new MemoryStream()) {
using (StreamWriter sw = new StreamWriter(ms))
{
using (JsonWriter writer = new JsonTextWriter(sw))
{
serializer.Serialize(writer, Data);
}
}
byte[] b = ms.ToArray();
await context.HttpContext.Response.Body.WriteAsync(b);
}
}
}