软件推广网站,wordpress使用支付宝当面付,苏州建设工程招投标网,物流网站建设相关的问题前言以前.NetCore是不内置JSON库的#xff0c;所以大家都用Newtonsoft的JSON库#xff0c;而且也确实挺好用的#xff0c;不过既然官方出了标准库#xff0c;那更方便更值得我们多用用#xff0c;至少不用每次都nuget安装Newtonsoft.Json库了。不过日常开发使用中会有一些… 前言以前.NetCore是不内置JSON库的所以大家都用Newtonsoft的JSON库而且也确实挺好用的不过既然官方出了标准库那更方便更值得我们多用用至少不用每次都nuget安装Newtonsoft.Json库了。不过日常开发使用中会有一些问题本文记录一下解决方法欢迎交流~文章末尾包含小彩蛋字符编码问题默认的 System.Text.Json 序列化的时候会把所有的非 ASCII 的字符进行转义这就会导致很多时候我们的一些非 ASCII 的字符就会变成 \uxxxx 这样的形式很多场景下并不太友好我们可以配置字符编码来解决被转义的问题。例子var testObjnew {Name 测试,Value 123
};var json JsonSerializer.Serialize(testObj);
Console.WriteLine(json);输出{Name:\u6D4B\u8BD5,Value:123}在我们序列化的时候可以指定一个 JsonSerializeOptions而这个 JsonSerializeOptions 中有一个 Encoder 我们可以用来配置支持的字符编码不支持的就会被转义而默认只支持 ASCII 字符。所以解决方法如下var json JsonSerializer.Serialize(testObj, new JsonSerializerOptions()
{Encoder JavaScriptEncoder.Create(UnicodeRanges.All)
})
Console.WriteLine(json);输出结果{Name:测试,Value:123}字符转义问题对于一些包含 html 标签的文本即使指定了所有字符集也会被转义这是出于安全考虑。如果觉得不需要转义也可以配置配置使用 JavaScriptEncoder.UnsafeRelaxedJsonEscaping 即可。示例代码var testObj new {Name 测试,Value 123,Code ptest/p
};var json JsonSerializer.Serialize(testObj, new JsonSerializerOptions {Encoder JavaScriptEncoder.Create(UnicodeRanges.All)
});
Console.WriteLine(json);输出{Name:测试,Value:123,Code:\u003Cp\u003Etest\u003C/p\u003E}可以看到HTML代码被转义了这很明显就不行解决方法var json JsonSerializer.Serialize(testObj, new JsonSerializerOptions {Encoder JavaScriptEncoder.UnsafeRelaxedJsonEscaping
});输出结果{Name:测试,Value:123,Code:ptest/p}搞定对象套娃递归问题这个问题在我之前的一篇文章中有详细说到Asp-Net-Core开发笔记接口返回json对象出现套娃递归问题当时我是用Newtonsoft.Json来解决的不过当我把这篇文章发布到博客园之后有大佬指出.NetCore标准库System.Text.Json中也有解决这个问题的方法于是我这里也来记录一下~首先建立几个实体类internal class EntityBase {public string Id { get; set; }
}
internal class CrawlTask : EntityBase {/// summary/// 爬虫名称/// /summarypublic string Name { get; set; }/// summary/// 创建这个爬虫的用户/// /summarypublic User User { get; set; }/// summary/// 用户ID/// /summarypublic string? UserId { get; set; }
}
internal class User : EntityBase {/// summary/// 用户名/// /summarypublic string Name { get; set; }/// summary/// 用户创建的爬虫/// /summarypublic ListCrawlTask CrawlTasks { get; set; }
}然后用模拟数据来重现问题//模拟数据
var crawlTask new CrawlTask { Name 爬虫名称, UserId 0f3d4b2f-3b4e-4d08-8f4c-0009a316f041 };
var user new User { Name 用户名, CrawlTasks new ListCrawlTask { crawlTask } };
crawlTask.User user;// 输出
var json2 JsonSerializer.Serialize(crawlTask);
Console.WriteLine(json2);输出结果直接报错Unhandled exception. System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger tha
n the maximum allowed depth of 64. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles. Path: $.User.CrawlTasks.User.CrawlTasks.U
ser.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.Us
er.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.Name.
...我们都知道了这是对象的套娃递归问题了所以接下来直接上解决方法var json2 JsonSerializer.Serialize(crawlTask,new JsonSerializerOptions {Encoder JavaScriptEncoder.UnsafeRelaxedJsonEscaping,WriteIndented true,ReferenceHandler ReferenceHandler.IgnoreCycles
});
Console.WriteLine(json2);ReferenceHandler.IgnoreCycles方式是.Net6新增加的可以实现和Newtonsoft.Json里ReferenceLoopHandling.Ignore差不多的效果。最终输出效果如下{Name: 爬虫名称,User: {Name: 用户名,CrawlTasks: [null],Id: null},UserId: 0f3d4b2f-3b4e-4d08-8f4c-0009a316f041,Id: null
}可以看到导致套娃递归的属性变成了null不过这个和Newtonsoft.Json实现的效果还是有点差异的在我之前的文章里Newtonsoft.Json实现的效果是{name: test crawl123,user: {name: string,crawlTasks: null,id: 0f3d4b2f-3b4e-4d08-8f4c-0009a316f041},userId: 0f3d4b2f-3b4e-4d08-8f4c-0009a316f041,id: 4d52d83b-f3ec-47c6-ab26-e241c09c14d1
}可以看到的是crawlTask.user.crawlTasks这个属性有差别System.Text.Json是一个数组然后里面有一个null对象而Newtonsoft.Json是把这个属性直接置为null相比之下我更喜欢Newtonsoft.Json的实现因为在前端解析的时候可以很清晰的得到一个空对象而不是装着空对象的数组有点绕口……后记说实话JSON处理还是Python这类动态语言比较方便像上面那些问题Python加个ensure_ascii参数就行虽然C#也不难比如import jsontest_obj {name: 测试,value: 123,code: ptest/p
}
print(json.dumps(test_obj, ensure_asciiFalse))有时我还喜欢加个indent参数这样输出来的JSON字符串更好看json.dumps(test_obj, ensure_asciiFalse, indent2)输出结果{Name: 测试,Value: 123,Code: ptest/p
}