首页 新闻 搜索 专区 学院

.netcore3.1 内置序列化在设置全局序列化 Encoder 配置的情况下还是无效

0
悬赏园豆:20 [已解决问题] 解决于 2020-05-09 09:43

需求:system.text.json.JsonSerializer.Serialize(returnData) ,由于 returnData 对象种的的其中一个属性是中文的。当我调用上面这个方法时,序列化出来的还是转码之后的字符集。
我在 startup 设置了全局序列化配置项

services.AddControllers().AddJsonOptions(config =>
 {
       Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
  });

结果控制器端调用 JsonSerializer.Serialize(returnData) 还是中文转码字符集
刚开始以为 UnsafeRelaxedJsonEscaping 没效果,就按 https://q.cnblogs.com/q/115234/ 上的问题全部来一遍,发现还是不行。

之后我做了以下措施:
在控制器注入 JsonOption 发现我之前加的全局设置都存在。但是不知在使用这个方法时没效果。
后来我在源码上看到这么一行代码
JsonSerializer.Serialize 在没有传 setting 的时候是调用了 JsonSerializerOptions.s_defaultOptions 这个单例对象,但是往后查我就不知道是在哪里进行赋值的了,而且在我另一个项目这么写是没问题的。
所以想请问下,这种情况是什么原因导致的?

备注:直接调用 JsonSerializer.Serialize(returnData, option) 这样是没有问题的

我所有的分都上了

< >
分享
最佳答案
0

.net core 3.1 还不支持全局设置 JsonSerializer 的 JsonSerializerOptions ,需要在 Serialize 方法中传入。

var json = JsonSerializer.Serialize(
    new { Title = "代码改变世界" },
    new JsonSerializerOptions { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) });

详见 How to globally set default options for System.Text.Json.JsonSerializer?

收获园豆:20
dudu | 高人七级 |园豆:39035 | 2020-05-08 20:47

也可以通过注入 IOptions<JsonOptions> 使用 Statup 中配置的 JsonOptions

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly JsonOptions _jsonOptions;

    public HomeController(ILogger<HomeController> logger, IOptions<JsonOptions> jsonOptions)
    {
        _logger = logger;
        _jsonOptions = jsonOptions.Value;
    }

    public IActionResult Index()
    {
        var json = JsonSerializer.Serialize(
            new { Title = "代码改变世界" },
            _jsonOptions.JsonSerializerOptions);
        return Content(json);
    }
}
dudu | 园豆:39035 (高人七级) | 2020-05-08 21:28

@dudu: 谢谢,我还以为支持。不过由于知道了源代码里面的结构,也知道 JsonSerializerOptions.s_defaultOptions 是一个单例,所以可以采用另一种方式来达到全局序列化器的作用,代码如下:
再 startup.Configure 方法种写入

var fieldInfo = typeof(JsonSerializerOptions).GetField("s_defaultOptions", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Instance);

 var options = fieldInfo.GetValue(null) as JsonSerializerOptions;
 options.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;

这样就不用在每个序列化方法去传入 option 了

沉睡的木木夕 | 园豆:13 (初学一级) | 2020-05-09 09:43

@沉睡的木木夕: 赞!巧妙使用反射解决了问题。

dudu | 园豆:39035 (高人七级) | 2020-05-09 10:52
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册