序列化为JSON时有条件地更改某些属性的类型

时间:2019-05-08 03:57:17

标签: c# .net json.net

我有一个自定义类,正在使用JSON.NET对其进行序列化。 在该类中,我们将其称为posInvoice,我拥有诸如UnitPriceQuantityTotalAmount之类的字符串类型的属性。当我将序列化的对象作为POST请求发送到端点时,此方法工作正常。

现在我有另一个端点,该端点接受相同的类posInvoice。但是,此端点期望这些值改为小数。

在我的代码中处理此问题的最佳方法是什么?我应该只创建另一个类并更改属性类型吗?我已经研究并试图在Stack Overflow中寻找类似的情况,但找不到任何东西。

1 个答案:

答案 0 :(得分:1)

这是我要采取的方法:

  1. 使用小数点定义PosInvoice类,因为这是最适合金额的数据类型。
  2. 创建一个自定义JsonConverter类,可在序列化期间使用该类将小数转换为字符串。
  3. 将转换器与需要将金额作为字符串的端点一起使用;否则可以省略。

模型类:

public class PosInvoice
{
    public string Description { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal Quantity { get; set; }
    public decimal TotalAmount { get; set; }
}

转换器:

public class InvoiceAmountsAsStringsConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(PosInvoice);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        PosInvoice invoice = (PosInvoice)value;
        JsonObjectContract contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(typeof(PosInvoice));
        writer.WriteStartObject();
        foreach (JsonProperty prop in contract.Properties)
        {
            writer.WritePropertyName(prop.PropertyName);
            object propValue = prop.ValueProvider.GetValue(invoice);
            if (propValue is decimal)
            {
                writer.WriteValue(((decimal)propValue).ToString(CultureInfo.InvariantCulture));
            }
            else
            {
                serializer.Serialize(writer, propValue);
            }
        }
        writer.WriteEndObject();
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

用法:

public static string SerializeInvoice(PosInvoice invoice, bool serializeDecimalsAsStrings)
{
    var settings = new JsonSerializerSettings { Formatting = Formatting.Indented };
    if (serializeDecimalsAsStrings)
    {
        settings.Converters.Add(new InvoiceAmountsAsStringsConverter());
    }
    return JsonConvert.SerializeObject(invoice, settings);
}

此处的工作演示:https://dotnetfiddle.net/4beAW3