私の問題は、(標準のPascalCaseとは対照的に)ASP.NET MVCコントローラーメソッドから ActionResult sでキャメルケース化された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"
}
どうやってこれをするの?
私はMats Karlssonの blog でこの問題に対する優れた解決策を見つけました。解決策は、JSON.NETを介してデータをシリアライズする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)};
}
または、簡単に言えば:
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
};
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にシリアル化するための拡張メソッドを作成することもできます。
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");
ASP.NET Core MVCでは。
public IActionResult Foo()
{
var data = GetData();
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
return Json(data, settings);
}
以下はオブジェクトの配列をシリアル化して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);
}
2番目のパラメータとして渡されたJsonSerializerSettingsインスタンスに注目してください。それがcamelCaseを実現させるものです。
単純な方が良い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
};
}
}
私はこのようにしました:
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になることができます。
ファイル「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()
};
}