如何从 ASP.NET MVC 控制器方法返回由 JSON.NET 序列化的驼峰案例 JSON



我的问题是我希望通过 ASP.NET MVC控制器方法的ActionResults返回camelCased(而不是标准的PascalCase)JSON数据,由 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"
}

我该怎么做?

或者,简单地说:

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

我在Mats Karlsson的博客上找到了这个问题的一个很好的解决方案。解决方案是编写 ActionResult 的子类,该子类通过 JSON.NET 序列化数据,将后者配置为遵循驼峰案例约定:

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

对于 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();
我认为这是

您正在寻找的简单答案。它来自Shawn Wildermuth的博客:

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

将 Json 命名策略属性添加到类定义中。

[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

自定义筛选器的替代方法是创建一个扩展方法,以将任何对象序列化为 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");

IMO 越简单越好!

你为什么不这样做?

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

您必须在文件"启动.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()
        };
    }

下面是一个操作方法,它通过序列化对象数组来返回 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 实例。这就是骆驼案发生的原因。

在 ASP.NET 核心MVC中。

    public IActionResult Foo()
    {
        var data = GetData();
        var settings = new JsonSerializerSettings 
        { 
            ContractResolver = new CamelCasePropertyNamesContractResolver() 
        });
        return Json(data, settings);
    }

我确实喜欢这个:

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的能力,当然这取决于:)

如果你在.net core web api或IHttpAction结果中返回ActionResult,那么你只需在Ok()方法中包装你的模型,该方法将与前端的大小写匹配并为你序列化它。无需使用 JsonConvert。 :)

由于.net core和以下的.net5,.net6,.net7,.net8 ASP .NET Core使用System.Text.Json.JsonSerializer而不是来自NewtonSoft的库,因此来自@aknuds1和@silvio的原始答案不是最新的。

设置属性命名转换:

////In Program.cs or in submodules, while sonfiguring services on startup:
services
  .AddJsonOptions(options =>
  {
    options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
    ////And other options for example for enum:
    //options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
    ////and for DateOnly we can register custom converter:
    //options.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter());
  });
////Then in controller:
[HttpGet]
public async Task<IActionResult> FooMethod(CancellationToken cancellationToken)
{
    var data = await GetData(cancellationToken);
    return Ok(data);
}

要手动转换为 JSON 字符串,请执行以下操作:

var jsonSerializerOptions = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
////And other settings like:
//jsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter());
var jsonStr = System.Text.Json.JsonSerializer.Serialize(data, jsonSerializerOptions);

自定义转换器示例:

//Actual for .net6 if your DTO contains DateOnly field
public class DateOnlyJsonConverter : JsonConverter<DateOnly>
{
    private const string Format = "yyyy-MM-dd";
    public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var str = reader.GetString();
        return string.IsNullOrEmpty(str)? default : DateOnly.ParseExact(str, Format, CultureInfo.InvariantCulture);
    }
    public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString(Format, CultureInfo.InvariantCulture));
    }
}

install-package Microsoft.AspNetCore.Mvc.NewtonsoftJson

这解决了我的问题

相关内容

  • 没有找到相关文章

最新更新