我有一个需要格式化输出json的十进制货币,与文化指定我的对象我序列化,对象可以嵌套,所以我不能预设序列化器中的选项。目前我这样做的方式是使用格式化输出的额外字符串属性。NewtonSoft JsonConverter - 访问其他属性
[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;}
我的问题是如何访问转换器包含对象的文化财产。
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;
}
}
As请求示例JSON。
对于一个Contract
类别的数组,每个类都有一个Cost和一个Culture。
[{ FormattedCost : "£5000.00"}, { FormattedCost : "$8000.00"}, { FormattedCost : "€599.00"}]
实际的对象要复杂得多,嵌套Assets的多个字段会有自己的数字。另外并非所有小数都是货币。
我真的不想为合约本身编写自定义序列化程序,因为每次属性更改时都必须对其进行修改。
理想的解决方案是能够使用转换器属性标记某些小数属性,以便它可以处理它。
我想去的另一种方式是用十进制隐式转换为小数属性创建一个自定义类,但是由于某些属性是基于以前的结果计算的属性,因此会变得更加复杂。
替代方法
我有一个变通为我的使用情况,但它使用反射来获得串行私有变量。
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
@DavidG是的,但问题是在writeJson里面我无法弄清楚如何访问父对象和它的属性。 –
给我们你迄今为止的,然后我们可以提供帮助。 – DavidG