序列化期间在类定义中强制使用十进制类型 [英] Force decimal type in class definition during serialization

查看:80
本文介绍了序列化期间在类定义中强制使用十进制类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我上课.该类的成员之一具有作为Decimal的子类型.默认的Json序列化器(不直接使用.某些no-sql库用于读取/写入),将这些Decimal值转换为Double.由于外部库在内部对对象进行了序列化,因此我正在寻找一种添加JsonProperty的方法,以使其强制FloatParseHandling.Decimal标志.我发现本文.但是,我们专门在序列化期间设置了我无法访问的标志.

I have a class. One of the members of the class is having subtypes as Decimal. Default Json serializer (not directly used. Used by some no-sql libraries for read/write), converts these Decimal values as Double. Since, external library internally serializes the object, I'm looking for a way to add JsonProperty such that it forces FloatParseHandling.Decimal flag. I have found this article. But, there we are specifically setting the flag during serialization which I don't have access to.

class TestData
{
    [JsonProperty(???)] // I need to apply property only at this level.
    public List<Row> rows;
}

// this class is being used by other APIs.
class Row
{ 
    public string myString { get; set; }
    // this will have int, string, 'decimal' types. Decimal type gets auto converted to Double and gets rounded
    public List<dynamic> values { get; set; } 
}

推荐答案

FloatParseHandling 指定浮点数的方式,例如读取JSON文本时将解析1.0和9.9.(在写入或序列化期间不适用,当Json.NET应该同时以必要的精度写入decimaldouble值时.)没有内置属性可在反序列化期间临时切换 JsonReader.FloatParseHandling 一个特定的属性.反序列化诸如

FloatParseHandling specifies how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. (It is not applicable during writing or serialization, when Json.NET should write both decimal and double values with as much precision as necessary.) There is no built-in attribute to temporarily toggle JsonReader.FloatParseHandling during deserialization of a specific property. When deserializing a statically typed property such as

List<decimal> values { get; set; }

这不是问题,因为序列化程序会告知读者所需的浮点类型.仅当反序列化为dynamic属性时,这才成为问题.

this is not an issue because the serializer tells the reader the required floating-point type. Only when deserializing to a dynamic property does this become problematic.

因此,您可以创建一个自定义JsonConverter 临时重置JsonReader.FloatParseHandling的值,然后分配并填充要反序列化的对象,如下所示:

Thus what you can do is to create a custom JsonConverter that temporarily resets the value of JsonReader.FloatParseHandling, then allocates and populates the object being deserialized, like so:

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属性:

Then apply it to your rows property as follows:

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

示例工作 .Net小提琴.

顺便说一句,请注意,如果您有一个动态属性,该属性可能具有十进制值,如下所示:

As an aside, note that, if you have a dynamic property that might have a decimal value, like so:

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

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

then applying the converter directly to the property will not work. This is because, at the time JsonConverter.ReadJson() is called, the reader has already advanced to the value string and tokenized it as a double. Thus the converter must be applied to a container type or property, e.g.:

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

这与该问题的具体情况相吻合,因为您希望仅将Row中的反序列化浮点值解释为decimal.

This dovetails with the specific case of this question since you want the deserialized floating-point values inside Row to be interpreted as decimal only within TestData.

这篇关于序列化期间在类定义中强制使用十进制类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆