遇到问题:
RuoYi.Net
使用 Oracle
库,SYS_MENU
菜单表的 MENU_ID
创建为 NUMBER(19)
类型,Vue
前端新增菜单保存到数据库的 MENU_ID
,以及后端返回给前端的 MENU_ID
没问题(ORM
使用的是SqlSugar,SqlSugar
新增入库时如果主键为 long
类型则自动生成雪花ID
),但在前端显示时发现精度丢失,如下:
数据库中 MENUID
为 1978349139955683328
前端显示 MENUID
为 1978349139955683300
解决办法:
参见 SqlSugar
官网: https://www.donet5.com/Doc/8nuge/2561
或者在 RuoYi.Admin\Startup.cs
中,修改如下代码:
csharp
.AddNewtonsoftJson(options =>
{
// 忽略循环引用
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
// 忽略所有 null 属性
//options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
// long 类型序列化时转 string, 防止 JavaScript 出现精度溢出问题
options.SerializerSettings.Converters.AddLongTypeConverters(); // 这一行扩展方法
})
RuoYi.Framework\JsonSerialization\Extensions\NewtonsoftJsonExtensions.cs,如下:
csharp
using RuoYi.Framework.JsonSerialization;
namespace Newtonsoft.Json;
/// <summary>
/// Newtonsoft.Json 拓展
/// </summary>
[SuppressSniffer]
public static class NewtonsoftJsonExtensions
{
/// <summary>
/// 添加 DateTime/DateTime?/DateTimeOffset/DateTimeOffset? 类型序列化处理
/// </summary>
/// <param name="converters"></param>
/// <param name="outputFormat"></param>
/// <param name="localized">自动转换 DateTimeOffset 为当地时间</param>
/// <returns></returns>
public static IList<JsonConverter> AddDateTimeTypeConverters(this IList<JsonConverter> converters, string outputFormat = "yyyy-MM-dd HH:mm:ss", bool localized = false)
{
converters.Add(new NewtonsoftJsonDateTimeJsonConverter(outputFormat));
converters.Add(new NewtonsoftNullableJsonDateTimeJsonConverter(outputFormat));
converters.Add(new NewtonsoftJsonDateTimeOffsetJsonConverter(outputFormat, localized));
converters.Add(new NewtonsoftJsonNullableDateTimeOffsetJsonConverter(outputFormat, localized));
return converters;
}
/// <summary>
/// 添加 long/long? 类型序列化处理
/// </summary>
/// <param name="converters"></param>
/// <param name="overMaxLengthOf17">是否超过最大长度 17 再处理</param>
/// <remarks></remarks>
public static IList<JsonConverter> AddLongTypeConverters(this IList<JsonConverter> converters, bool overMaxLengthOf17 = false)
{
converters.Add(new NewtonsoftJsonLongToStringJsonConverter(overMaxLengthOf17));
converters.Add(new NewtonsoftJsonNullableLongToStringJsonConverter(overMaxLengthOf17));
return converters;
}
/// <summary>
/// 添加 DateOnly/DateOnly? 类型序列化处理
/// </summary>
/// <param name="converters"></param>
/// <returns></returns>
public static IList<JsonConverter> AddDateOnlyConverters(this IList<JsonConverter> converters)
{
#if !NET5_0
converters.Add(new NewtonsoftJsonDateOnlyJsonConverter());
converters.Add(new NewtonsoftJsonNullableDateOnlyJsonConverter());
#endif
return converters;
}
/// <summary>
/// 添加 TimeOnly/TimeOnly? 类型序列化处理
/// </summary>
/// <param name="converters"></param>
/// <returns></returns>
public static IList<JsonConverter> AddTimeOnlyConverters(this IList<JsonConverter> converters)
{
#if !NET5_0
converters.Add(new NewtonsoftJsonTimeOnlyJsonConverter());
converters.Add(new NewtonsoftJsonNullableTimeOnlyJsonConverter());
#endif
return converters;
}
}
RuoYi.Framework\JsonSerialization\Converters\NewtonsoftJson\NewtonsoftJsonLongToStringJsonConverter.cs,如下:
csharp
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace RuoYi.Framework.JsonSerialization;
/// <summary>
/// 解决 long 精度问题
/// </summary>
[SuppressSniffer]
public class NewtonsoftJsonLongToStringJsonConverter : JsonConverter<long>
{
/// <summary>
/// 构造函数
/// </summary>
public NewtonsoftJsonLongToStringJsonConverter()
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="overMaxLengthOf17"></param>
public NewtonsoftJsonLongToStringJsonConverter(bool overMaxLengthOf17 = false)
{
OverMaxLengthOf17 = overMaxLengthOf17;
}
/// <summary>
/// 是否超过最大长度 17 再处理
/// </summary>
public bool OverMaxLengthOf17 { get; set; }
/// <summary>
/// 反序列化
/// </summary>
/// <param name="reader"></param>
/// <param name="objectType"></param>
/// <param name="existingValue"></param>
/// <param name="hasExistingValue"></param>
/// <param name="serializer"></param>
/// <returns></returns>
public override long ReadJson(JsonReader reader, Type objectType, long existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var jt = JValue.ReadFrom(reader);
return jt.Value<long>();
}
/// <summary>
/// 序列化
/// </summary>
/// <param name="writer"></param>
/// <param name="value"></param>
/// <param name="serializer"></param>
public override void WriteJson(JsonWriter writer, long value, JsonSerializer serializer)
{
if (OverMaxLengthOf17)
{
if (value.ToString().Length <= 17) writer.WriteValue(value);
else writer.WriteValue(value.ToString());
}
else writer.WriteValue(value.ToString());
}
}
/// <summary>
/// 解决 long? 精度问题
/// </summary>
[SuppressSniffer]
public class NewtonsoftJsonNullableLongToStringJsonConverter : JsonConverter<long?>
{
/// <summary>
/// 构造函数
/// </summary>
public NewtonsoftJsonNullableLongToStringJsonConverter()
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="overMaxLengthOf17"></param>
public NewtonsoftJsonNullableLongToStringJsonConverter(bool overMaxLengthOf17 = false)
{
OverMaxLengthOf17 = overMaxLengthOf17;
}
/// <summary>
/// 是否超过最大长度 17 再处理
/// </summary>
public bool OverMaxLengthOf17 { get; set; }
/// <summary>
/// 反序列化
/// </summary>
/// <param name="reader"></param>
/// <param name="objectType"></param>
/// <param name="existingValue"></param>
/// <param name="hasExistingValue"></param>
/// <param name="serializer"></param>
/// <returns></returns>
public override long? ReadJson(JsonReader reader, Type objectType, long? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var jt = JValue.ReadFrom(reader);
return jt.Value<long?>();
}
/// <summary>
/// 序列化
/// </summary>
/// <param name="writer"></param>
/// <param name="value"></param>
/// <param name="serializer"></param>
public override void WriteJson(JsonWriter writer, long? value, JsonSerializer serializer)
{
if (value == null) writer.WriteNull();
else
{
var newValue = value.Value;
if (OverMaxLengthOf17)
{
if (newValue.ToString().Length <= 17) writer.WriteValue(newValue);
else writer.WriteValue(newValue.ToString());
}
else writer.WriteValue(newValue.ToString());
}
}
}