序列化期间强制类定义中的十进制类型

时间:2018-01-10 03:14:50

标签: c# json json.net

我上课了。该类的一个成员具有Decimal的子类型。默认的Json序列化程序(不直接使用。由某些无sql库用于读/写),将这些Decimal值转换为Double。因为,外部库在内部序列化对象,我正在寻找一种方法来添加JsonProperty,以强制 columns: [ ... { data: "Priority" , render: renderPriorityAsString, }, ... function renderPriorityAsString(priority) { const priorityToString = { 0: 'low', 1: 'med', 2: 'high', }; return priorityToString[priority] || `${priority} does not have a lookup value`; } 标志。我找到了this article。但是,我们在序列化期间专门设置了我无法访问的标志。

FloatParseHandling.Decimal

1 个答案:

答案 0 :(得分:1)

FloatParseHandling指定如何浮点数,例如在读取JSON文本时解析1.0和9.9。(在写入或序列化期间不适用,当Json.NET应尽可能精确地写入decimaldouble值时。)在特定属性的反序列化期间,没有内置属性可临时切换JsonReader.FloatParseHandling。反序列化静态类型属性(如

)时
List<decimal> values { get; set; }

这不是问题,因为序列化程序告诉读者所需的浮点类型。只有在反序列化为dynamic属性时才会出现问题。

因此,你可以做的是创建一个临时重置JsonReader.FloatParseHandling值的custom JsonConverter,然后分配并填充被反序列化的对象,如下所示:

public class FloatParseHandlingConverter : JsonConverter
{
    readonly FloatParseHandling floatParseHandling;

    public FloatParseHandlingConverter(FloatParseHandling floatParseHandling)
    {
        this.floatParseHandling = floatParseHandling;
    }

    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var old = reader.FloatParseHandling;
        try
        {
            reader.FloatParseHandling = floatParseHandling;
            existingValue = existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
            serializer.Populate(reader, existingValue);
            return existingValue;
        }
        finally
        {
            reader.FloatParseHandling = old;
        }
    }

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

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后将其应用于rows属性,如下所示:

class TestData
{
    [JsonConverter(typeof(FloatParseHandlingConverter), FloatParseHandling.Decimal)]
    public List<Row> rows;
}

示例工作.Net fiddle

顺便说一句,请注意,如果您有一个可能具有小数值的动态属性,请执行以下操作:

public class Parent
{
    dynamic value { get; set; }
}

然后将转换器直接应用于属性将不起作用。这是因为,在调用JsonConverter.ReadJson()时,读者已经前进到值字符串并将其标记为double 。因此,转换器必须应用于容器类型或属性,例如:

[JsonConverter(typeof(FloatParseHandlingConverter), FloatParseHandling.Decimal)]
public class Parent
{
    // [JsonConverter(typeof(FloatParseHandlingConverter), FloatParseHandling.Decimal)] will not work
    dynamic value { get; set; }
}

这与此问题的具体情况相吻合,因为您希望Row内的反序列化浮点值仅在decimal内解释为TestData