Hal*_*ard 22 c# json javascriptserializer
我上课了
public class Money
{
public string Currency { get; set; }
public decimal Amount { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
并希望将其序列化为JSON.如果我使用JavaScriptSerializer我得到
{"Currency":"USD","Amount":100.31000}
Run Code Online (Sandbox Code Playgroud)
由于API我必须符合需要JSON数量最多两位小数,我觉得应该可以以某种方式改变JavaScriptSerializer序列化十进制字段的方式,但我不知道如何.还有就是SimpleTypeResolver你可以在构造函数中通过,但它只能在类型,只要我能理解工作.该JavaScriptConverter,您可以通过添加RegisterConverters(...)似乎是要进行Dictionary.
我想得到
{"Currency":"USD","Amount":100.31}
Run Code Online (Sandbox Code Playgroud)
在我序列化之后.此外,改为双倍是不可能的.我可能需要进行一些舍入(100.311应该变为100.31).
有谁知道如何做到这一点?是否有替代方案JavaScriptSerializer可以让您更详细地控制序列化?
Bra*_*ite 17
到目前为止,我对所有这些技术并不完全满意.JsonConverterAttribute似乎是最有希望的,但我无法忍受硬编码参数和每个选项组合的转换器类的扩散.
所以,我提交了一个PR,它增加了将各种参数传递给JsonConverter和JsonProperty的能力.它已被上游接受,我预计将在下一个版本中发布(6.0.5之后的下一个版本)
然后你可以这样做:
public class Measurements
{
[JsonProperty(ItemConverterType = typeof(RoundingJsonConverter))]
public List<double> Positions { get; set; }
[JsonProperty(ItemConverterType = typeof(RoundingJsonConverter), ItemConverterParameters = new object[] { 0, MidpointRounding.ToEven })]
public List<double> Loads { get; set; }
[JsonConverter(typeof(RoundingJsonConverter), 4)]
public double Gain { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
有关示例,请参阅CustomDoubleRounding()测试.
小智 10
为了将来参考,可以通过创建自定义在Json.net中非常优雅地实现 JsonConverter
public class DecimalFormatJsonConverter : JsonConverter
{
private readonly int _numberOfDecimals;
public DecimalFormatJsonConverter(int numberOfDecimals)
{
_numberOfDecimals = numberOfDecimals;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var d = (decimal) value;
var rounded = Math.Round(d, _numberOfDecimals);
writer.WriteValue((decimal)rounded);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
}
public override bool CanRead
{
get { return false; }
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(decimal);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您使用构造函数显式地在代码中创建序列化程序,这将工作正常,但我认为装饰相关属性更好JsonConverterAttribute,在这种情况下,类必须具有公共的无参数构造函数.我通过创建一个特定于我想要的格式的子类来解决这个问题.
public class SomePropertyDecimalFormatConverter : DecimalFormatJsonConverter
{
public SomePropertyDecimalFormatConverter() : base(3)
{
}
}
public class Poco
{
[JsonConverter(typeof(SomePropertyDecimalFormatConverter))]
public decimal SomeProperty { get;set; }
}
Run Code Online (Sandbox Code Playgroud)
自定义转换器源自Json.NET文档.
我只是经历了同样的麻烦,因为我有一些小数被序列化1.00和一些1.0000.这是我的改变:
创建一个JsonTextWriter,可以将值四舍五入到4位小数.然后,每个小数将四舍五入为4位小数:1.0变为1.0000,而1.0000000也变为1.0000
private class JsonTextWriterOptimized : JsonTextWriter
{
public JsonTextWriterOptimized(TextWriter textWriter)
: base(textWriter)
{
}
public override void WriteValue(decimal value)
{
// we really really really want the value to be serialized as "0.0000" not "0.00" or "0.0000"!
value = Math.Round(value, 4);
// divide first to force the appearance of 4 decimals
value = Math.Round((((value+0.00001M)/10000)*10000)-0.00001M, 4);
base.WriteValue(value);
}
}
Run Code Online (Sandbox Code Playgroud)
使用您自己的编写器而不是标准编写器:
var jsonSerializer = Newtonsoft.Json.JsonSerializer.Create();
var sb = new StringBuilder(256);
var sw = new StringWriter(sb, CultureInfo.InvariantCulture);
using (var jsonWriter = new JsonTextWriterOptimized(sw))
{
jsonWriter.Formatting = Formatting.None;
jsonSerializer.Serialize(jsonWriter, instance);
}
Run Code Online (Sandbox Code Playgroud)
在第一种情况下000,不会造成任何损害,该值仍然相同,并且将被反序列化为完全相同的值。
在第二种情况下,JavascriptSerializer 将无法帮助您。不应该更改数据JavacriptSerializer,因为它将数据序列化为众所周知的格式,它不提供成员级别的数据转换(但它提供自定义对象转换器)。你想要的是转换+序列化,这是一个两阶段的任务。
两个建议:
1) 使用DataContractJsonSerializer: 添加另一个对值进行四舍五入的属性:
public class Money
{
public string Currency { get; set; }
[IgnoreDataMember]
public decimal Amount { get; set; }
[DataMember(Name = "Amount")]
public decimal RoundedAmount { get{ return Math.Round(Amount, 2); } }
}
Run Code Online (Sandbox Code Playgroud)
2) 克隆对值进行四舍五入的对象:
public class Money
{
public string Currency { get; set; }
public decimal Amount { get; set; }
public Money CloneRounding() {
var obj = (Money)this.MemberwiseClone();
obj.Amount = Math.Round(obj.Amount, 2);
return obj;
}
}
var roundMoney = money.CloneRounding();
Run Code Online (Sandbox Code Playgroud)
我想json.net也不能做到这一点,但我不是 100% 确定。
| 归档时间: |
|
| 查看次数: |
25441 次 |
| 最近记录: |