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

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&lt;long&gt;),这有时也很有用。 关于“编辑”——如果有人遇到同样的问题——它不想为我工作,因为***.com/questions/24620110/…【参考方案2】:

只有string 属性的view model 怎么样,像这样:

public class CustomerEntityViewModel

    public string ID  get; set; 
    public string Name  get; set; 

现在您只需处理strings 和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

以上是关于在序列化中将长数字转换为字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中将数字转换为字符串,反之亦然

如何在 TypeScript 中将字符串转换为数字?

如何在 TypeScript 中将字符串转换为数字?

在python中将字符串转换为数字[关闭]

如何在freemarker模板中将字符串转换为数字

如何在存储过程中将数字转换为字符串[关闭]