在序列化中将长数字转换为字符串

问题描述 投票:0回答:6
我有一个使用 long 作为 ID 的定制类。但是,当我使用 ajax 调用我的操作时,我的 ID 被截断并且丢失了最后 2 个数字,因为 JavaScript 在处理大数字时会丢失精度。我的解决方案是给我的 JavaScript 提供一个字符串,但 ID 必须在服务器端保留很长。

有没有办法将属性序列化为字符串?我正在寻找某种属性。

控制器

public class CustomersController : ApiController { public IEnumerable<CustomerEntity> Get() { yield return new CustomerEntity() { ID = 1306270928525862486, Name = "Test" }; } }

型号

public class CustomerEntity { public long ID { get; set; } public string Name { get; set; } }

JSON 结果

[{"Name":"Test","ID":1306270928525862400}]
    
c# json asp.net-mvc-4 asp.net-web-api
6个回答
31
投票
您可以创建一个自定义

JsonConverter

 并将其应用到您的财产上。

以下是一个示例(

注意:我之前没有使用过这个 api,所以它可能还可以进一步改进,但是以下应该可以给您一个粗略的想法):

public class Person { [JsonConverter(typeof(IdToStringConverter))] public long ID { get; set; } public string Name { get; set; } } public class IdToStringConverter : JsonConverter { public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JToken jt = JValue.ReadFrom(reader); return jt.Value<long>(); } public override bool CanConvert(Type objectType) { return typeof(System.Int64).Equals(objectType); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, value.ToString()); } }

Web API 操作:

public Person Post([FromBody]Person person) { return person; }

要求:

POST http://asdfasdf/api/values HTTP/1.1 Host: servername:9095 Connection: Keep-Alive Content-Type: application/json Content-Length: 42 {"ID":"1306270928525862400","Name":"Mike"}

回应:

HTTP/1.1 200 OK Content-Length: 42 Content-Type: application/json; charset=utf-8 Server: Microsoft-HTTPAPI/2.0 Date: Fri, 28 Jun 2013 17:02:18 GMT {"ID":"1306270928525862400","Name":"Mike"}

编辑 如果您不想使用属性来修饰属性,则可以将其添加到 Converters 集合中。示例:

config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new IdToStringConverter());
    

2
投票
仅具有

view model

 属性的 
string
 怎么样,如下所示:

public class CustomerEntityViewModel { public string ID { get; set; } public string Name { get; set; } }

现在您只需处理

string

,并且 
JSON
 序列化问题就消失了。


2
投票
当我调用 json 序列化器时,我可能会创建一个匿名类型;

JsonConvert.SerializeObject(new { instance.Name, instance.ID.ToString() } );

如果您的类有 20 个或其他字段,这将成为一个非常丑陋的解决方案,我会向名为

ID

 的类添加一个字符串,将 long 更改为 
lID
 或其他内容,并使用序列化器设置来忽略 long序列化时,生成的 json 将只有字符串版本。

例如,有几种不同的属性可以实现此目的;

public class CustomerEntity { [ScriptIgnore] public long _ID { get; set; } public string ID { get; set; } public string Name { get; set; } }

不会序列化

_ID


    


2
投票
根据您的情况,您可能会在 JSON 序列化期间使用 getter 和 setter 将属性伪装为字符串。

public class Money { [JsonIgnore] public decimal Money { get; set; } [JsonProperty("money")] public string MoneyAsString { get { return Money.ToString("0.00"); } set { Money = decimal.Parse(value); } } }
    

0
投票
也许一个可行的解决方法是使用另一种类型的 ID?例如,您可以使用 GUID。使用 GUID,您永远不会超出范围,而且我认为默认情况下这将被序列化为字符串。


0
投票
在新的

System.Text.Json

课程中。

您可以使用这个:

using System; using System.Text.Json; using System.Text.Json.Serialization; namespace XXX.Common { /// <summary> /// /// </summary> public class LongToStringConverter : JsonConverter<long> { public override long Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return Convert.ToInt64(reader.GetString()); } public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString()); } } }
您可以在

Startup.cs

中使用它

services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new LongToStringConverter()); });
有关更多信息,请查看 

如何在 .NET 中编写用于 JSON 序列化(编组)的自定义转换器

© www.soinside.com 2019 - 2024. All rights reserved.