Як я можу повернути camelCase JSON, серіалізований JSON.NET, з методів контролера ASP.NET MVC?


246

Моя проблема полягає в тому, що я хочу повернути дані JSON camelCased (на відміну від стандартного PascalCase) за допомогою ActionResult s методів контролера ASP.NET MVC, серіалізованого JSON.NET .

Як приклад розглянемо наступний клас C #:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

За замовчуванням, коли повертається екземпляр цього класу з контролера MVC як JSON, він буде серіалізуватися таким чином:

{
  "FirstName": "Joe",
  "LastName": "Public"
}

Я хотів би, щоб вона була серіалізована (від JSON.NET) у вигляді:

{
  "firstName": "Joe",
  "lastName": "Public"
}

Як це зробити?

Відповіді:


389

або, просто кажучи:

JsonConvert.SerializeObject(
    <YOUR OBJECT>, 
    new JsonSerializerSettings 
    { 
        ContractResolver = new CamelCasePropertyNamesContractResolver() 
    });

Наприклад:

return new ContentResult
{
    ContentType = "application/json",
    Content = JsonConvert.SerializeObject(new { content = result, rows = dto }, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }),
    ContentEncoding = Encoding.UTF8
};

2
Однак це складніше використовувати, оскільки потрібно налаштувати ContentResult для кожного методу контролера.
aknuds1

2
Так, я розумію, що ваша відповідь була багаторазовим рішенням, я хочу зробити більш зрозумілим, що це лише параметр методу Serialize.
WebDever

1
Якщо ви повертаєте JSON з Controllerметоду, ви, ймовірно, повинні використовувати an ApiController, і в цьому випадку ця відповідь чудово працює.
Саймон Хартчер

1
@SimonHartcher Поміркуйте, хоч питання, але не загальний випадок.
aknuds1

1
Дійсний тип вмісту для JSON є application/json, ні text/plain.
Фред

94

Я знайшов чудове рішення цієї проблеми в блозі Матса Карлссона . Рішення полягає в написанні підкласу ActionResult, який серіалізує дані за допомогою JSON.NET, налаштовуючи останній на виконання конвенції camelCase:

public class JsonCamelCaseResult : ActionResult
{
    public JsonCamelCaseResult(object data, JsonRequestBehavior jsonRequestBehavior)
    {
        Data = data;
        JsonRequestBehavior = jsonRequestBehavior;
    }

    public Encoding ContentEncoding { get; set; }

    public string ContentType { get; set; }

    public object Data { get; set; }

    public JsonRequestBehavior JsonRequestBehavior { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (JsonRequestBehavior == JsonRequestBehavior.DenyGet && String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.");
        }

        var response = context.HttpContext.Response;

        response.ContentType = !String.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
        if (ContentEncoding != null)
        {
            response.ContentEncoding = ContentEncoding;
        }
        if (Data == null)
            return;

        var jsonSerializerSettings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
        response.Write(JsonConvert.SerializeObject(Data, jsonSerializerSettings));
    }
}

Потім використовуйте цей клас у своєму методі контролера MVC:

public ActionResult GetPerson()
{
    return new JsonCamelCaseResult(new Person { FirstName = "Joe", LastName = "Public" }, JsonRequestBehavior.AllowGet)};
}

3
Ідеальна відповідь: чистий і багаторазовий! Дякую.
шліфувальник

1
Поки це рішення все ще працює. але це було запропоновано 4 роки тому. Чи є у нас краще рішення?
SharpCoder

59

Для WebAPI перегляньте це посилання: http://odetocode.com/blogs/scott/archive/2013/03/25/asp-net-webapi-tip-3-camelcasing-json.aspx

В основному додайте цей код до своїх Application_Start:

var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();

4
Веб-API та MVC об’єднані в ASP.NET 6
AlexFoxGill

1
Посилання для зручності; ця установка справді чудово грає з цією відповіддю: stackoverflow.com/a/26068063/398630 (інше питання, але я використовую їх разом, і це посилання може врятувати мене та інших людей у ​​майбутньому).
BrainSlugs83

37

Я думаю, що це проста відповідь, яку ви шукаєте. Це з блогу Шона Уайлдермута :

// Add MVC services to the services container.
services.AddMvc()
  .AddJsonOptions(opts =>
  {
    opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
  });

2
Мої вибачення, хлопці. Я занадто швидко прочитав цю публікацію. Це для ASP.NET 5.
Квантіум

8
За іронією долі, я прийшов сюди, шукаючи відповідь на запитання, на яке ви тут відповіли, тому, хоча це не було відповіддю на питання ОП, мені це все одно допомогло. Дякую! :)
porcus

1
Я другий, що сказав @porcus! Дякую @Quantium!
Громер

4
fyi Для ASP.NET Core 1.0 - справа за верблюдами за замовчуванням OOTB
Chris Marisic

3
Виявляється, це не (точно) за замовчуванням для .NET Core 1.0 зрештою. Це рішення впливає на динамічні властивості, і на них не впливає за замовчуванням. stackoverflow.com/questions/41329279/…
Нільс Брінч

13

Альтернативою користувальницькому фільтру є створення методу розширення для серіалізації будь-якого об’єкта в JSON.

public static class ObjectExtensions
{
    /// <summary>Serializes the object to a JSON string.</summary>
    /// <returns>A JSON string representation of the object.</returns>
    public static string ToJson(this object value)
    {
        var settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            Converters = new List<JsonConverter> { new StringEnumConverter() }
        };

        return JsonConvert.SerializeObject(value, settings);
    }
}

Потім зателефонуйте, коли повертаєтесь з дії контролера.

return Content(person.ToJson(), "application/json");

Елегантний і простий.
markau

1
Ви навіть можете перенести налаштування в статичне поле лише для читання та додати метод доповнення FromJson.
Пара в Алеї

8

Простіше, краще ІМО!

Чому ти цього не зробиш?

public class CourseController : JsonController
{
    public ActionResult ManageCoursesModel()
    {
        return JsonContent(<somedata>);
    }
}

Простий контролер базового класу

public class JsonController : BaseController
{
    protected ContentResult JsonContent(Object data)
    {
        return new ContentResult
        {
            ContentType = "application/json",
             Content = JsonConvert.SerializeObject(data, new JsonSerializerSettings { 
              ContractResolver = new CamelCasePropertyNamesContractResolver() }),
            ContentEncoding = Encoding.UTF8
        };
    }
}

7

В ASP.NET Core MVC.

    public IActionResult Foo()
    {
        var data = GetData();

        var settings = new JsonSerializerSettings 
        { 
            ContractResolver = new CamelCasePropertyNamesContractResolver() 
        });

        return Json(data, settings);
    }

А ще краще, помістіть його у файл Startup.cs.
FatAlbert

6

Нижче наведено метод дії, який повертає рядок json (cameCase) шляхом серіалізації масиву об’єктів.

public string GetSerializedCourseVms()
    {
        var courses = new[]
        {
            new CourseVm{Number = "CREA101", Name = "Care of Magical Creatures", Instructor ="Rubeus Hagrid"},
            new CourseVm{Number = "DARK502", Name = "Defence against dark arts", Instructor ="Severus Snape"},
            new CourseVm{Number = "TRAN201", Name = "Transfiguration", Instructor ="Minerva McGonal"}
        };
        var camelCaseFormatter = new JsonSerializerSettings();
        camelCaseFormatter.ContractResolver = new CamelCasePropertyNamesContractResolver();
        return JsonConvert.SerializeObject(courses, camelCaseFormatter);
    }

Зверніть увагу на екземпляр JsonSerializerSettings, переданий як другий параметр. Ось що змушує верблюда статися.


4

Мені було так:

public static class JsonExtension
{
    public static string ToJson(this object value)
    {
        var settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            NullValueHandling = NullValueHandling.Ignore,
            ReferenceLoopHandling = ReferenceLoopHandling.Serialize
        };
        return JsonConvert.SerializeObject(value, settings);
    }
}

це простий метод розширення в ядрі MVC, він дасть можливість ToJson () кожному об'єкту у вашому проекті. На мою думку, у проекті MVC більшість об'єктів повинна мати можливість стати json, звичайно, це залежить :)


Подумайте про вилучення змінної "settings" поза методом (як приватне статичне поле "camelCaseSettings"), щоб ви не ініціалізували нову змінну щоразу, коли виклик методу ToJson.
Екус

4

Ви повинні встановити настройки у файлі "Startup.cs"

Ви також повинні визначити це у значеннях за замовчуванням JsonConvert, це якщо ви хочете пізніше безпосередньо використовувати бібліотеку для серіалізації об'єкта.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
            .AddJsonOptions(options => {
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });
        JsonConvert.DefaultSettings = () => new JsonSerializerSettings
        {
            NullValueHandling = NullValueHandling.Ignore,
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
    }

Зауважте, що ця відповідь є правильною для ASP.NET Core, але не для ASP.NET (що є основою у питанні).
Нейт Барбеттіні

0

Якщо ви повертаєте ActionResult у .net core api, або результат IHttpAction, ви можете просто обгорнути свою модель методом Ok (), який буде відповідати випадку на передньому кінці та серіалізувати його для вас. Не потрібно використовувати JsonConvert. :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.