24 Star 210 Fork 83

jackletter/DotNetCommon

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
JsonHelper.cs 12.87 KB
一键复制 编辑 原始数据 按行查看 历史
using DotNetCommon.Extensions;
using DotNetCommon.Serialize;
using System;
using System.Collections.Concurrent;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace DotNetCommon
{
/// <summary>
/// json帮助类
/// </summary>
public static class JsonHelper
{
/// <summary>
/// 格式化json
/// </summary>
/// <param name="srcJson">原json</param>
/// <param name="isIntend">是否缩进</param>
/// <param name="removeComment">是否移除注释</param>
/// <returns></returns>
public static string Format(string srcJson, bool isIntend = true, bool removeComment = true)
{
if (srcJson.IsNullOrEmptyOrWhiteSpace()) return srcJson;
using var doc = JsonSerializer.Deserialize<JsonDocument>(srcJson, new JsonSerializerOptions
{
AllowTrailingCommas = true,
ReadCommentHandling = removeComment ? JsonCommentHandling.Skip : JsonCommentHandling.Allow,
});
var res = JsonSerializer.Serialize(doc, new JsonSerializerOptions
{
WriteIndented = isIntend,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
});
return res;
}
/// <summary>
/// 判断json是否是数组
/// </summary>
/// <param name="srcJson"></param>
/// <returns></returns>
public static bool IsArray(string srcJson)
{
if (srcJson.IsNullOrEmptyOrWhiteSpace()) return false;
if (srcJson.StartsWith("[")) return true;
if (srcJson.StartsWith("{")) return false;
var index = 0;
var len = srcJson.Length;
var singleComment = false;
var multiComment = false;
var preMultiEnd = false;
var preComment = false;
while (index < len)
{
var c = srcJson[index];
index++;
if (singleComment)
{
if (c == '\n')
{
singleComment = false;
}
continue;
}
if (multiComment)
{
if (preMultiEnd)
{
if (c == '/')
{
multiComment = false;
continue;
}
else if (c == '*')
{
continue;
}
else
{
preMultiEnd = false;
continue;
}
}
else
{
if (c == '*') preMultiEnd = true;
continue;
}
}
//
if (preComment)
{
if (c == '*')
{
//进入多行
multiComment = true;
preComment = false;
continue;
}
else if (c == '/')
{
//进入单行
singleComment = true;
preComment = false;
continue;
}
preComment = false;
continue;
}
//啥模式也没有
if (c == '/')
{
//预进入单行或多行注释模式
preComment = true;
continue;
}
else if (c == '[')
{
return true;
}
else if (c == '{')
{
return false;
}
else
{
continue;
}
}
return false;
}
/// <summary>
/// 获取默认的 <c>JsonSerializerOptions</c>, 配置如下:
/// <list type="bullet">
/// <item>输出时 中文原样输出,而不是 \uxxxx; Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping</item>
/// <item>输出时 包含字段; IncludeFields = true</item>
/// <item>输出时 不包含只读字段; IgnoreReadOnlyFields = true</item>
/// <item>输出时 忽略循环引用; ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles</item>
/// <item>读取时 允许多余的逗号; AllowTrailingCommas = true</item>
/// <item>读取时 跳过注释; ReadCommentHandling = System.Text.Json.JsonCommentHandling.Skip</item>
/// <item>读取时 允许字符串转数字; NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString</item>
/// <item>读取时 大小写不敏感; PropertyNameCaseInsensitive = true</item>
/// </list>
/// </summary>
public static JsonSerializerOptions GetDefaultJsonSerializerOptions(
string dateTimeFormatString = null,
string dateTimeOffsetFormatString = null,
string dateOnlyOffsetFormatString = null,
string timeOnlyOffsetFormatString = null,
bool enum2String = false
)
{
return _getDefaultJsonSerializerOptions(dateTimeFormatString, dateTimeOffsetFormatString, dateOnlyOffsetFormatString, timeOnlyOffsetFormatString, enum2String);
}
internal static JsonSerializerOptions _getDefaultJsonSerializerOptions(
string dateTimeFormatString = null,
string dateTimeOffsetFormatString = null,
string dateOnlyOffsetFormatString = null,
string timeOnlyOffsetFormatString = null,
bool enum2String = false,
bool ignoreNull = false,
bool lowerCamelCase = false,
bool lowerCamelCaseDictionaryKey = false,
bool isIntend = false,
bool number2String = false,
bool readOnly = false
)
{
if (readOnly)
{
var key = $"{dateTimeFormatString}:{dateTimeOffsetFormatString}:{dateOnlyOffsetFormatString}:{timeOnlyOffsetFormatString}:{enum2String}:{ignoreNull}:{lowerCamelCase}:{lowerCamelCaseDictionaryKey}:{isIntend}:{number2String}";
return _cache.GetOrAdd(key, () =>
{
return act();
});
}
else
{
return act();
}
JsonSerializerOptions act()
{
var options = new JsonSerializerOptions();
Configure(options,
dateTimeFormatString: dateTimeFormatString,
dateTimeOffsetFormatString: dateTimeOffsetFormatString,
dateOnlyOffsetFormatString: dateOnlyOffsetFormatString,
timeOnlyOffsetFormatString: timeOnlyOffsetFormatString,
ignoreNull: ignoreNull,
enum2String: enum2String,
lowerCamelCase: lowerCamelCase,
lowerCamelCaseDictionaryKey: lowerCamelCaseDictionaryKey,
isIntend: isIntend,
number2String: number2String);
return options;
}
}
private static ConcurrentDictionary<string, JsonSerializerOptions> _cache = new();
/// <summary>
/// 对已有的 <c>JsonSerializerOptions</c> 进行配置,以增强兼容性,可用在 web开发中,如:
/// <code>
/// services.AddControllers().AddJsonOptions(options =>JsonHelper.Configure(options.JsonSerializerOptions, dateTimeFormatString: "yyyy-MM-dd", lowerCamelCase: true));
/// </code>
/// </summary>
/// <param name="options">源对象</param>
/// <param name="dateTimeFormatString">日期时间格式(DateTime)</param>
/// <param name="dateTimeOffsetFormatString">日期时间格式(DateTimeOffset)</param>
/// <param name="dateOnlyOffsetFormatString">日期时间格式(DateOnly)</param>
/// <param name="timeOnlyOffsetFormatString">日期时间格式(TimeOnly)</param>
/// <param name="number2String">是否将数字转为字符串</param>
/// <param name="ignoreNull">是否忽略null值的属性</param>
/// <param name="enum2String">是否将枚举转换为字符串</param>
/// <param name="lowerCamelCase">属性名称的首字母是否小写</param>
/// <param name="lowerCamelCaseDictionaryKey">字典key首字母是否小写</param>
/// <param name="isIntend">是否格式缩进</param>
public static void Configure(JsonSerializerOptions options,
string dateTimeFormatString = null,
string dateTimeOffsetFormatString = null,
string dateOnlyOffsetFormatString = null,
string timeOnlyOffsetFormatString = null,
bool enum2String = false,
bool ignoreNull = false,
bool lowerCamelCase = false,
bool lowerCamelCaseDictionaryKey = false,
bool isIntend = false,
bool number2String = false)
{
//中文直接输出,而不是 \uxxxx 形式
options.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
//允许输出Field
options.IncludeFields = true;
//忽略只读Field
options.IgnoreReadOnlyFields = true;
//忽略循环引用
options.ReferenceHandler = ReferenceHandler.IgnoreCycles;
//允许存在多余的逗号
options.AllowTrailingCommas = true;
//跳过注释
options.ReadCommentHandling = JsonCommentHandling.Skip;
//允许将 "123" 转为数字 123
//允许 {"Prop":"NaN"} 浮点型,但不允许 {\"Prop\":NaN},这点无法做到与Newtonsoft兼容
options.NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.AllowNamedFloatingPointLiterals;
//允许忽略属性名大小写
options.PropertyNameCaseInsensitive = true;
//解决 "" => int? 报错问题
options.Converters.Add(new NullAbleConverter());
//解决 1 => bool 报错问题
options.Converters.Add(new JsonConverterBool());
//解决 "Open" => enum 报错问题
options.Converters.Add(new JsonEnumConverter(enum2String));
//解决反序列化问题: 123 => "123"
options.Converters.Add(new JsonConverterString());
//DateOnly & TimeOnly
if (Environment.Version.Major == 6)
{
if (dateOnlyOffsetFormatString.IsNotNullOrEmptyOrWhiteSpace()) options.Converters.Add(new JsonConverterDateOnly(dateOnlyOffsetFormatString));
else options.Converters.Add(new JsonConverterDateOnly());
if (timeOnlyOffsetFormatString.IsNotNullOrEmptyOrWhiteSpace()) options.Converters.Add(new JsonConverterTimeOnly(timeOnlyOffsetFormatString));
else options.Converters.Add(new JsonConverterTimeOnly());
}
else
{
if (dateOnlyOffsetFormatString.IsNotNullOrEmptyOrWhiteSpace()) options.Converters.Add(new JsonConverterDateOnly(dateOnlyOffsetFormatString));
if (dateOnlyOffsetFormatString.IsNotNullOrEmptyOrWhiteSpace()) options.Converters.Add(new JsonConverterDateOnly(dateOnlyOffsetFormatString));
if (timeOnlyOffsetFormatString.IsNotNullOrEmptyOrWhiteSpace()) options.Converters.Add(new JsonConverterTimeOnly(timeOnlyOffsetFormatString));
}
//Datetime & DateTimeOffset
if (dateTimeFormatString.IsNotNullOrEmptyOrWhiteSpace()) options.Converters.Add(new JsonConverterDatetime(dateTimeFormatString));
else options.Converters.Add(new JsonConverterDatetime());
if (dateTimeOffsetFormatString.IsNotNullOrEmptyOrWhiteSpace()) options.Converters.Add(new JsonConverterDateTimeOffset(dateTimeOffsetFormatString));
else options.Converters.Add(new JsonConverterDateTimeOffset());
if (ignoreNull) options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
if (lowerCamelCase) options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
if (lowerCamelCaseDictionaryKey) options.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
if (isIntend) options.WriteIndented = true;
if (number2String) options.NumberHandling = options.NumberHandling | JsonNumberHandling.WriteAsString;
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C#
1
https://gitee.com/jackletter/DotNetCommon.git
git@gitee.com:jackletter/DotNetCommon.git
jackletter
DotNetCommon
DotNetCommon
master

搜索帮助

23e8dbc6 1850385 7e0993f3 1850385