Имена свойств строкового нижнего регистра из Json() в ASP.NET MVC
Учитывая следующий класс,
public class Result
{
public bool Success { get; set; }
public string Message { get; set; }
}
Я возвращаю одно из них в действие контроллера, например,
return Json(new Result() { Success = true, Message = "test"})
Однако моя инфраструктура клиентской стороны ожидает, что эти свойства будут иметь более низкий успех и сообщение. Без фактического наличия имен свойств нижнего регистра является то, что способ достичь этой мысли вызовет нормальную функцию Json?
Ответы
Ответ 1
Способ достижения этого состоит в реализации пользовательского JsonResult
например, здесь: создание пользовательского ValueType и сериализация с пользовательским JsonResult (исходная ссылка не работает).
И используйте альтернативный сериализатор, такой как JSON.NET, который поддерживает такое поведение, например:
Product product = new Product
{
ExpiryDate = new DateTime(2010, 12, 20, 18, 1, 0, DateTimeKind.Utc),
Name = "Widget",
Price = 9.99m,
Sizes = new[] {"Small", "Medium", "Large"}
};
string json =
JsonConvert.SerializeObject(
product,
Formatting.Indented,
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
}
);
Результаты в
{
"name": "Widget",
"expiryDate": "\/Date(1292868060000)\/",
"price": 9.99,
"sizes": [
"Small",
"Medium",
"Large"
]
}
Ответ 2
Изменение сериализатора просто, если вы используете веб-API, но, к сожалению, MVC сам использует JavaScriptSerializer
без возможности изменить это, чтобы использовать JSON.Net.
Ответ Джеймса и ответ Даниэла дает вам гибкость JSON.Net, но означает, что везде, где вы обычно делаете return Json(obj)
, вам нужно изменить на return new JsonNetResult(obj)
или аналогичный, который, если у вас есть большой проект, может оказаться проблемой, а также не очень гибкий, если вы передумаете в сериализаторе, который хотите использовать.
Я решил спуститься по маршруту ActionFilter
. В приведенном ниже коде вы можете предпринять любые действия с помощью JsonResult
и просто применить к нему атрибут для использования JSON.Net(с нижестоящими свойствами):
[JsonNetFilter]
[HttpPost]
public ActionResult SomeJson()
{
return Json(new { Hello = "world" });
}
// outputs: { "hello": "world" }
Вы даже можете настроить это для автоматического применения ко всем действиям (только с незначительным снижением производительности при проверке is
):
FilterConfig.cs
// ...
filters.Add(new JsonNetFilterAttribute());
Код
public class JsonNetFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Result is JsonResult == false)
return;
filterContext.Result = new CustomJsonResult((JsonResult)filterContext.Result);
}
private class CustomJsonResult : JsonResult
{
public CustomJsonResult(JsonResult jsonResult)
{
this.ContentEncoding = jsonResult.ContentEncoding;
this.ContentType = jsonResult.ContentType;
this.Data = jsonResult.Data;
this.JsonRequestBehavior = jsonResult.JsonRequestBehavior;
this.MaxJsonLength = jsonResult.MaxJsonLength;
this.RecursionLimit = jsonResult.RecursionLimit;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet
&& String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
throw new InvalidOperationException("GET not allowed! Change JsonRequestBehavior to AllowGet.");
var response = context.HttpContext.Response;
response.ContentType = String.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;
if (this.ContentEncoding != null)
response.ContentEncoding = this.ContentEncoding;
if (this.Data != null)
{
var json = JsonConvert.SerializeObject(
this.Data,
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
response.Write(json);
}
}
}
}
Ответ 3
С моим решением вы можете переименовать все необходимые свойства.
Я нашел часть решения здесь и на 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
Хотя это старый вопрос, надеюсь, фрагмент кода ниже будет полезен для других,
Я сделал ниже с веб-API MVC5.
public JsonResult<Response> Post(Request request)
{
var response = new Response();
//YOUR LOGIC IN THE METHOD
//.......
//.......
return Json<Response>(response, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() });
}
Ответ 5
Вы можете добавить этот параметр в Global.asax
, и он будет работать везде.
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
//....
JsonConvert.DefaultSettings = () =>
{
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
PreserveReferencesHandling = PreserveReferencesHandling.None,
Formatting = Formatting.None
};
return settings;
};
//....
}
}