【发布时间】:2018-05-31 16:09:36
【问题描述】:
我需要将十进制的输出 json 格式化为货币,并指定我正在序列化的对象的文化,该对象可以嵌套,因此我无法在序列化程序中预设选项。我目前的做法是使用额外的字符串属性来格式化输出。
[JsonIgnore]
public decimal Cost {get;set;}
[JsonIgnore]
public CultureInfo Culture {get;set;}
public string AsCurrency(decimal value) {
return string.Format(this.Culture, "{0:c}", value);
}
[JsonProperty("FormattedCost")]
public string FormatedCost {
get { return this.AsCurrency(this.Cost); }
}
我有很多属性要处理,我不关心反序列化,JsonObject 被不同的语言用来填充 PDF,所以我想要字符串值。
理想情况下,我想要一个JsonConverter,这样我就可以了
[JsonProperty("FormattedCost")]
[JsonConverter(typeof(MyCurrencyConverter))]
public decimal Cost {get;set;}
我遇到的问题是如何访问转换器中包含对象的 Culture 属性。
public class MyCurrencyConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var culture = // How do I get the Culture from the parent object?
writer.WriteValue(string.format(culture, "{0:c}", (decimal)value);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return typeof(decimal) == objectType;
}
}
作为请求的示例 JSON。
对于Contract 类的数组,每个类都有一个 Cost 和一个 Culture。
[{ FormattedCost : "£5000.00"}, { FormattedCost : "$8000.00"}, { FormattedCost : "€599.00"}]
实际的对象要复杂得多,具有嵌套资产的多个字段,这些字段将有自己的数字。此外,并非所有小数都是货币。
我真的不想为合约本身编写自定义序列化程序,因为每次属性更改时我都必须修改它。
理想的解决方案是能够使用转换器属性标记某些十进制属性,以便它可以处理它。
我正在考虑的另一种方法是为十进制属性创建一个自定义类,并从十进制进行隐式转换,但是由于某些属性是基于先前结果计算的属性,因此变得更加复杂。
解决方法
我的用例有一个解决方法,但它使用反射来获取序列化程序中的私有变量。
var binding = BindingFlags.NonPublic | BindingFlags.Instance;
var writer = serializer.GetType()
.GetMethod("GetInternalSerializer", binding)
?.Invoke(serializer, null);
var parent = writer?.GetType()
.GetField("_serializeStack", binding)
?.GetValue(writer) is List<object> stack
&& stack.Count > 1 ? stack[stack.Count - 2] as MyType: null;
在我测试的用例中,这给了我父对象,但它没有使用公共 API。
【问题讨论】:
-
你试过写
MyCurrencyConverter吗? (PS 你的第一个代码块没有编译) -
@DavidG 是的,但问题出在 writeJson 内部,我无法弄清楚如何访问父对象及其属性。
-
给我们您目前所拥有的,然后我们可以提供帮助。
-
所以可以有多个嵌套对象,每个对象都有自己的文化?
-
也许您也可以提供一些 JSON 示例?