轉進 ASP.NET Core 世界,依循過去寫 MVC 經驗,加上參考網路技術文章(當然,還有流著奶與蜜的 Stackoverflow) 大致還算都順利,但不時發現新的眉角。

今天遇到的問題是 Razor Page 傳回 JsonResult 時,中文字元被轉成 UCN (Unicode Character Name,例如:"\u9ED1\u6697\u57F7\u884C\u7DD2") 編碼。Razor Page 程式範例如下,OnGetJsonData() 時使用 new JsonResult() 回傳簡單資料物件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using PTSWeb.Models.Data;

namespace PTSWeb.Pages
{
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;

        public IndexModel(ILogger<IndexModel> logger,)
        {
            _logger = logger;
        }

        public void OnGet()
        {

        }

        public ActionResult OnGetJsonData()
        {
            return new JsonResult(new
            {
                Blog = "darkthread",
                Name = "黑暗執行緒"
            });
        }
    }
}

如下圖所示,在預設情況下,中文字串將會被轉換成 UCN,另外屬性名稱的第一個字元被轉成小寫(我慣用大寫,程式碼產生器處理時可保持前後端一致):

這類問題對對我不算陌生,之前在 cshtml 就遇過:ASP.NET Core View 中文變 & # x4E2D; & # x6587;,大約知道與 Encoder 設定有關,差別在上回是 HtmlEncoder,ASP.NET Core 3.0 起預設改用 System.Text.Json 處理 JSON 序列化與反序列化,找到方法調整 System.Text.Json 的 Encoder 設定即可解決。

查到做法是在 Startup.ConfigureServices() 的 AddRazorPages()、AddControllers()、AddMvc() 後接上 AddJsonOptions() 修改預設設定:(我一併取消屬性名稱強制轉頭文字小寫(Camel Case)的功能)

public void ConfigureServices(IServiceCollection services)
{
    //... 略 ....
    services.AddRazorPages()
        .AddJsonOptions(options =>
        {
            //原本是 JsonNamingPolicy.CamelCase,強制頭文字轉小寫,我偏好維持原樣,設為null
            options.JsonSerializerOptions.PropertyNamingPolicy = null;
            //允許基本拉丁英文及中日韓文字維持原字元
            options.JsonSerializerOptions.Encoder = 
                JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.CjkUnifiedIdeographs);
        });
}

搞定!

不過,很有預感未來很有可能因為 System.Text.Json 的某個限制讓我想換回 Json.NET,所以提前部署,預圥查了切回去使用 Json.NET 的方法:

先用 NuGet 安裝 Microsoft.AspNetCore.Mvc.NewtonsoftJson:

AddRazorPages()、AddControllers()、AddMvc() 後方接 AddNewtonsoftJson():(Json.NET 在 ASP.NET Core 預設也會將屬性名稱轉成頭文字小寫,要保持原樣需呼叫 UseMemberCasing() )

services.AddRazorPages()
    .AddNewtonsoftJson(options =>
    {
        options.UseMemberCasing();
    });

Hint of how to change default JSON serialization and deserialization settings in ASP.NET Core.


Comments

# by Ike

「屬性名稱的第一個字元被轉成小寫」這很討厭,怎麼可以擅自改掉呢

Post a comment


96 - 50 =