在序列化中将长数字转换为字符串
Posted
技术标签:
【中文标题】在序列化中将长数字转换为字符串【英文标题】:Convert long number as string in the serialization 【发布时间】:2013-06-26 11:55:26 【问题描述】:我有一个使用 long as 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]
【问题讨论】:
【参考方案1】:您可能可以创建一个自定义 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());
【讨论】:
谢谢,太好了!该答案的唯一缺点是我们的实体继承自我们的 ORM 中的自定义实体模板,该模板用于我们拥有的每个项目(其中一些不是基于 Web 的)。这意味着将 Newtonsoft.JSON 的依赖项添加到 ORM,并且我们拥有的每个项目也需要 newtonsoft。我更喜欢不依赖于 DLL 的属性。 @Bruno:有一件事要警告你。该转换器会将所有长整数转换为字符串。您可能应该研究一些方法来进行一些检查,以便它不适用于应用程序范围以及任何性能增强,以便除了您期望的类型之外不触发此转换器,例如:CustomerEntity
我们很少使用 long 来表示不是 ID 的东西
不错的解决方案 - 值得一提的是它不处理 long?
(Nullable<long>
),这有时也很有用。
关于“编辑”——如果有人遇到同样的问题——它不想为我工作,因为***.com/questions/24620110/…【参考方案2】:
只有string
属性的view model
怎么样,像这样:
public class CustomerEntityViewModel
public string ID get; set;
public string Name get; set;
现在您只需处理string
s 和JSON
序列化问题就消失了。
【讨论】:
我认为他想在服务器端保持很长时间 @cinek - 他可以,因为他可以将CustomerEntity
模型类转换为 CustomerEntityViewModel
并将其传递给客户端,然后在返回服务器时可以将其转换回CustomerEntity
类,ID 又是 long
。我同意它正在跳跃,但如果需要这种精度,那么需要在某个地方进行一些到 string
的转换。
这意味着为我的每个实体创建一个视图模型(因为它们都使用长 ID)并复制每个实体中的每个属性
@Bruno - 可悲的是,这就是我的意思。 :-(
这种方法的问题是(在某些情况下,没有专门讨论这种情况)字符串的默认值与 int/long/etc' 不同。如果这些模型被用于向期望数字或零的端点发出请求,但随后得到一个空字符串,则它可能会失败或呈现不稳定的行为。这也是可以解决的,但是在一个地方创建一个 JSON 转换器并解决问题会更安全【参考方案3】:
当我调用 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
【讨论】:
【参考方案4】:根据您的情况,您可能会在 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);
【讨论】:
【参考方案5】:也许一个可行的解决方法是使用另一种类型的 ID?例如,您可以使用 GUID。使用 GUID,您将永远不会超出范围,而且我认为默认情况下这将被序列化为字符串。
【讨论】:
我无法更改类型,但我正在寻找一种方法来序列化一个长字符串,如 GUID以上是关于在序列化中将长数字转换为字符串的主要内容,如果未能解决你的问题,请参考以下文章