问题
Javascript 的 number 类型存在精度限制,浏览器反序列化 JSON 时,无法完整保留 long
类型的精度。
在 JSON 序列化时将 long
转换为 string
进行传递就可以保留精度。在 ASP.NET Core 中,可以创建一个 自定义 JsonConverter
来达到这一目的。
实现 long
和 string
转换的 JsonConverter
创建一个类 LongToStringJsonConverter
,示例代码(来自:https://github.com/cnblogs/Architecture/blob/main/src/Cnblogs.Architecture.Ddd.Cqrs.AspNetCore/LongToStringConverter.cs)
/// <summary>
/// JSON 序列化时,在 long 和 string 类型之间转换。
/// </summary>
public class LongToStringConverter : JsonConverter<long>
{/// <inheritdoc />public override long Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){if (reader.TokenType != JsonTokenType.String){return reader.GetInt64();}var raw = reader.GetString();if (string.IsNullOrWhiteSpace(raw)){throw new JsonException("string is empty");}var success = long.TryParse(raw, out var parsed);if (success == false){throw new JsonException("string value can't be converted to long");}return parsed;}/// <inheritdoc />public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options){writer.WriteStringValue(value.ToString());}
}
然后可以在应用代码里启用将刚刚写好的自定义 JsonConverter
,可以根据项目的不同需求,指定启用的范围。
仅对类中的某一字段启用:
public class TestDto
{[JsonConverter(typeof(LongToStringJsonConverter))]public long Id { get; set; }
}
对整个 API 项目全局启用:
新的 Minimal API 项目
// Program.csbuilder.Services.ConfigureHttpJsonOptions(options => options.SerializerOptions.Converters.Add(new LongToStringJsonConverter()));
传统的 MVC 项目
builder.Services.AddControllers().AddJsonOptions(options => options.SerializerOptions.Converters.Add(new LongToStringJsonConverter()))
在前端,如果使用 Typescript 的话,需要将对应类型从 number
改为 string
以实现正确的类型推断。
interface TestDto {// id: number;id: string;
}