我有一个使用长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}]
答案 0 :(得分:17)
您可以创建自定义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());
答案 1 :(得分:2)
只有view model
属性的string
怎么样,如下所示:
public class CustomerEntityViewModel
{
public string ID { get; set; }
public string Name { get; set; }
}
现在,您只处理string
和JSON
序列化问题。
答案 2 :(得分:2)
当我调用json序列化程序时,我可能只会创建一个匿名类型;
JsonConvert.SerializeObject(new { instance.Name, instance.ID.ToString() } );
如果您的类有20个或者某个字段,这将成为一个非常难看的解决方案,我会在名为ID
的类中添加一个字符串,将长度更改为lID
或其他内容并使用序列化设置在序列化时忽略long,因此生成的json只有字符串版本。
有几个不同的属性可以实现这一点,例如;
public class CustomerEntity
{
[ScriptIgnore]
public long _ID { get; set; }
public string ID { get; set; }
public string Name { get; set; }
}
不会序列化_ID
答案 3 :(得分:0)
也许一个可行的解决方法是使用另一种类型的ID?例如,您可以使用GUID。使用GUID,你永远不会超出界限,而且我认为这将被串行化为字符串。
答案 4 :(得分:0)
根据您的情况,您可能会使用getter和setter在JSON序列化期间将属性伪装成字符串。
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); }
}
}