从Web API返回驼峰式JSON

13

我正在尝试从ASP.Net Web API 2控制器返回驼峰式的JSON。我创建了一个只包含ASP.Net MVC和Web API部分的新Web应用程序。我像这样劫持了ValuesController:

public class ValuesController : ApiController
{
    public class Thing
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string ISBN { get; set; }
        public DateTime ReleaseDate { get; set; }

        public string[] Tags { get; set; }
    }

    // GET api/values
    public IHttpActionResult Get()
    {
        var thing = new Thing
        {
            Id = 123,
            FirstName = "Brian",
            ISBN = "ABC213", 
            ReleaseDate = DateTime.Now,
            Tags = new string[] { "A", "B", "C", "D"}
        };

        return Json(thing);
    }
}

在IE中运行此代码,我得到以下结果:

{"Id":123,"FirstName":"Brian","ISBN":"ABC213","ReleaseDate":"2014-10-20T16:26:33.6810554-04:00","Tags":["A","B","C","D"]}

K. Scott Allen的帖子中,讨论了这个主题后,我将以下内容添加到WebApiConfig.cs文件的Register方法中:

public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        var formatters = GlobalConfiguration.Configuration.Formatters;
        var jsonFormatter = formatters.JsonFormatter;
        var settings = jsonFormatter.SerializerSettings;
        settings.Formatting = Formatting.Indented;
        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }

然而,我的结果仍然存在大写字母。我是否漏掉了什么?我已经尝试了其他几种方法,但仍未奏效。


这个答案是否如此明显,以至于人们认为我应该自己想出来?到目前为止,我还没有得到任何反馈。我从一个新项目开始,但仍然无法让它正常工作。 - beaudetious
我仍然认为另一篇帖子中的答案是最好的:https://dev59.com/52Eh5IYBdhLWcg3wtFJE#22130487 - Xinan
6个回答

16
在您的WebApiConfig.cs文件中,请确保添加这两行代码。
// Serialize with camelCase formatter for JSON.
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

请确保您已安装Newtonsoft库。

希望这有所帮助。


不好意思,我已经尝试过了,Newtonsoft 已经安装了。 :( - beaudetious
我曾经遇到过类似的问题,你需要从OWIN的HttpConfig中获取格式化程序,而不是GlobalConfiguration。 - Luke De Feo
@LukeDeFeo,你能展示一下从OWIN的httpconfig中获取格式化程序的代码吗? - Dmitry Efimenko
2
我通过以下方式检索到了 jsonFormattervar jsonFormatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter; - TPoschel

9

看起来主要问题是我在使用JsonResult快捷方式的Json()动作结果方法:

public IHttpActionResult Get([FromUri] string domain, [FromUri] string username)
{
    var authInfo = BLL.GetAuthenticationInfo(domain, username);
    return Json(authInfo);
}

显然,它完全控制了结果的格式。如果我切换到返回HttpResponseMessage,则会按预期工作:

public HttpResponseMessage Get([FromUri] string domain, [FromUri] string username)
{
    var authInfo = BLL.GetAuthenticationInfo(domain, username);
    return Request.CreateResponse(HttpStatusCode.OK, authInfo);
}

我最终使用了Omar.Alani建议的WebApiConfig文件中的代码块(而不是我在原帖中使用的冗长代码)。但真正的罪魁祸首是JsonResult操作方法。希望这能帮助其他人。


6
我知道这个评论有点晚了,但我发现使用Ok(authInfo)会应用格式化程序,而使用Json(authInfo)则不会。 Ok方法将根据“Accept”标题应用相应的格式化程序。 然后,您仍可以返回IHttpActionResult - Eben Roux

5

在你的操作方法中,需要使用OK()而不是Json()

// GET api/values
public IHttpActionResult Get()
{
    var thing = new Thing
    {
        Id = 123,
        FirstName = "Brian",
        ISBN = "ABC213", 
        ReleaseDate = DateTime.Now,
        Tags = new string[] { "A", "B", "C", "D"}
    };

    // Use 'Ok()' instead of 'Json()'
    return Ok(thing);
}

3
在WebApiConfig的Register方法中添加以下代码:
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
WebApiConfig的完整代码如下:
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

        }
    }

请确保您已安装最新版本的Json.Net/Newtonsoft.Json,并且您的API操作方法返回以下方式的数据:
    [HttpGet]
    public HttpResponseMessage List()
    {
        try
        {
            var result = /*write code to fetch your result*/;
            return Request.CreateResponse(HttpStatusCode.OK, result);
        }
        catch (Exception ex)
        {
            return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
        }
    }

1

我正在使用Owin和DI(在我的情况下是AutoFac),所以这使得问题更加复杂。我的Startup.cs包含:

var apiconfig = new HttpConfiguration
{
    DependencyResolver = new AutofacWebApiDependencyResolver(container)
};
WebApiConfig.Register(apiconfig);

然后在我的 WebApiConfig.cs 文件中,我有以下内容:
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Web.Http;
using Microsoft.Owin.Security.OAuth;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        //  Setup json.Net for pretty output, easy human reading AND this formatter
        //  does that ONLY for browsers - best of both worlds: useful AND efficient/performant!
        config.Formatters.Clear();
        config.Formatters.Add(new BrowserJsonFormatter());
    }

    public class BrowserJsonFormatter : JsonMediaTypeFormatter
    {
        //  Since most browser defaults do not include an "accept type" specifying json, this provides a work around
        //  Default to json over XML - any app that wants XML can ask specifically for it  ;)
        public BrowserJsonFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
            SerializerSettings.Formatting = Formatting.Indented;
            SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            // Convert all dates to UTC
            SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
        }

        //  Change the return type to json, as most browsers will format correctly with type as text/html
        public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
        {
            base.SetDefaultContentHeaders(type, headers, mediaType);
            headers.ContentType = new MediaTypeHeaderValue("application/json");
        }
    }

0

也试试这个。

[AllowAnonymous]
[HttpGet()]
public HttpResponseMessage GetAllItems(int moduleId)
{
            HttpConfiguration config = new HttpConfiguration();
            config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;

            try
            {
                List<ItemInfo> itemList = GetItemsFromDatabase(moduleId);
                return Request.CreateResponse(HttpStatusCode.OK, itemList, config);
            }
            catch (System.Exception ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接