Web API 2:オブジェクトとそのサブオブジェクトで、camelCasedプロパティ名を使用してJSONを返す方法


104

更新

すべての回答をありがとう。私は新しいプロジェクトに参加していて、ようやくこれの最後に到達したようです。次のコードが実際に原因であるように見えます。

public static HttpResponseMessage GetHttpSuccessResponse(object response, HttpStatusCode code = HttpStatusCode.OK)
{
    return new HttpResponseMessage()
    {
        StatusCode = code,
        Content = response != null ? new JsonContent(response) : null
    };
}

他の場所...

public JsonContent(object obj)
{
    var encoded = JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore } );
    _value = JObject.Parse(encoded);

    Headers.ContentType = new MediaTypeHeaderValue("application/json");
}

私は、無害に見えるJsonContentをWebAPIであると想定して見落としていたが、そうではなかった。

これはどこでも使われています...最初に言ってもいいですか、wtf?それとも、「なぜ彼らはこれをしているのですか?」


元の質問が続きます

これは単純な構成設定であると思っていたかもしれませんが、今はあまりにも長い間、私を見過ごしていました。

私はさまざまな解決策と答えを見てきました:

https://gist.github.com/rdingwall/2012642

最新のWebAPIバージョンには適用されないようです...

以下は機能していないようです-プロパティ名はPascalCasedのままです。

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;

json.UseDataContractJsonSerializer = true;
json.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;

json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 

ここでMayankの答え:CamelCase JSON WebAPIサブオブジェクト(ネストされたオブジェクト、子オブジェクト)は、linq2sqlを使用しているため、生成されたコードにこれらの属性を追加する必要があることに気づくまで、不十分ですが実行可能な答えのように見えました...

これを自動的に行う方法はありますか?この「厄介」は、長い間私を悩ませてきました。



また、Linq2SQLが部分クラスを生成する理由もあります。また... Linq2SQL WTF ?!
アロン、

1
ありがとう、しかしこのリンクはMVCのためのものであり、私が使用しているWeb API 2であり、このようにコンテンツタイプを設定して文字列を返す方法があるかどうかはわかりませんが、ある場合はそうではありません。非常に適切な解決策のように。部分クラスについてのヒントもありがとうございます。ただし、部分クラスの他の部分で定義されたプロパティに属性を追加することは可能ですか?
トム

また、はい、linq2sql wtf ...私の決定ではありません:)
Tom

結果は同じですが、唯一の違いはを挿入する場所ですJsonSerializerstackoverflow.com/questions/13274625/...
アロン

回答:


175

すべてをまとめると、...

protected void Application_Start()
{
    HttpConfiguration config = GlobalConfiguration.Configuration;
    config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;
}

間違いなくそれをオンにする方法ですが、私の問題はこの設定が無視されていたことでした(私の回答を参照)
Tom

1
@トム・エルム...トムは何をjson.UseDataContractJsonSerializer = true;しているのか知っていましたか?Json.Netシリアル化に使用しないようにWebAPIに指示します。> _ <
2015

はい、今します。ただし、別の問題もありました。これを確認しました。私の答えを見てください。また、stackoverflow.com / questions / 28552567 /…
トム

1
実際、よく調べてみると、私は以前の結論に誤りがあったことがわかりました。私のアップデートを見てください。
トム

28

これは私のために働いたものです:

internal static class ViewHelpers
{
    public static JsonSerializerSettings CamelCase
    {
        get
        {
            return new JsonSerializerSettings {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            };
        }
    }
}

その後:

[HttpGet]
[Route("api/campaign/list")]
public IHttpActionResult ListExistingCampaigns()
{
    var domainResults = _campaignService.ListExistingCampaigns();
    return Json(domainResults, ViewHelpers.CamelCase);
}

クラスCamelCasePropertyNamesContractResolverNewtonsoft.Json.dllJson.NETライブラリに由来します。


3
このアプローチは、アプリケーションのすべてのAPIではなく、一部のAPIのみにキャメルケースを設定したい場合に非常に役立ちます。(Y)
droidbot 2016

15

それが判明

return Json(result);

原因となったのは、シリアル化プロセスがキャメルケースの設定を無視する原因でした。そして、

return Request.CreateResponse(HttpStatusCode.OK, result, Request.GetConfiguration());

私が探していたドロイドでした。

また

json.UseDataContractJsonSerializer = true;

作業中にスパナを入れていて、私が探していたドロイドではないことがわかりました。


これは実際には間違った答えです。質問の私の更新を参照してください。
トム

私は実際にこれが事実であることを発見しました。に戻るとJson(result)、PascalCaseにすべてが表示Content(StatusCode, result)されていましたが、戻ると期待どおりに機能しました。
DeeKayy90

12

Owin HostingとNinjectでは、上記のすべての回答がうまくいきませんでした。これが私のために働いたものです:

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // Get the ninject kernel from our IoC.
        var kernel = IoC.GetKernel();

        var config = new HttpConfiguration();

        // More config settings and OWIN middleware goes here.

        // Configure camel case json results.
        ConfigureCamelCase(config);

        // Use ninject middleware.
        app.UseNinjectMiddleware(() => kernel);

        // Use ninject web api.
        app.UseNinjectWebApi(config);
    }

    /// <summary>
    /// Configure all JSON responses to have camel case property names.
    /// </summary>
    private void ConfigureCamelCase(HttpConfiguration config)
    {
        var jsonFormatter = config.Formatters.JsonFormatter;
        // This next line is not required for it to work, but here for completeness - ignore data contracts.
        jsonFormatter.UseDataContractJsonSerializer = false;
        var settings = jsonFormatter.SerializerSettings;
#if DEBUG
        // Pretty json for developers.
        settings.Formatting = Formatting.Indented;
#else
        settings.Formatting = Formatting.None;
#endif
        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }
}

主な違いは、GlobalConfiguration.Configurationではなく、新しいHttpConfiguration()です。


OWINによるセルフホスティングには、これが最適です。ありがとう!
ジュリアンメルビル

3
Owinを使用している場合、このソリューションは完全に機能しますが、髪をすべて引き裂いた後でのみです。
Alastair 2017

10

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

            //This line sets json serializer's ContractResolver to CamelCasePropertyNamesContractResolver, 
            //  so API will return json using camel case
            config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

        }
    }


APIアクションメソッドが次の方法でデータを返し、最新バージョンのJson.Net/Newtonsoft.Jsonがインストールされていることを確認してください。

    [HttpGet]
    public HttpResponseMessage List()
    {
        try
        {
            var result = /*write code to fetch your result*/;
            return Request.CreateResponse(HttpStatusCode.OK, cruises);
        }
        catch (Exception ex)
        {
            return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
        }
    }

4

Owinスタートアップに次の行を追加します...

 public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var webApiConfiguration = ConfigureWebApi();            
        app.UseWebApi(webApiConfiguration);
    }

    private HttpConfiguration ConfigureWebApi()
    {
        var config = new HttpConfiguration();

        // ADD THIS LINE HERE AND DONE
        config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 

        config.MapHttpAttributeRoutes();
        return config;
    }
}

3

これはあいまいな例です。ルート属性がGET urlと一致しなかったが、GET urlがメソッド名と一致した場合、jsonserializerキャメルケースディレクティブは無視されます。

http:// website / api / geo / geodata

//uppercase fail cakes
[HttpGet]
[Route("countries")]
public async Task<GeoData> GeoData()
{
    return await geoService.GetGeoData();
}

//lowercase nomnomnom cakes
[HttpGet]
[Route("geodata")]
public async Task<GeoData> GeoData()
{
    return await geoService.GetGeoData();
}

2

以下の方法で解決しました。

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

0

BreezeでWebApiを使用していますが、Breezeコントローラーで非Breezeアクションを実行しようとすると、同じ問題が発生しました。Apprach Request.GetConfigurationを使用しようとしましたが、同じ結果が得られました。したがって、Request.GetConfigurationによって返されたオブジェクトにアクセスすると、要求によって使用されるシリアライザーは、breeze-serverが魔法をかけるために使用するものであることがわかります。とにかく、別のHttpConfigurationを作成する問題を解決しました。

public static HttpConfiguration BreezeControllerCamelCase
        {
            get
            {
                var config = new HttpConfiguration();
                var jsonSerializerSettings = config.Formatters.JsonFormatter.SerializerSettings;
                jsonSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                jsonSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;

                return config;
            }
        }

次のように、Request.CreateResponseでパラメータとして渡します。

return this.Request.CreateResponse(HttpStatusCode.OK, result, WebApiHelper.BreezeControllerCamelCase);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.