当前位置: 首页 > 面试题库 >

在Newtonsoft.Json中处理十进制值

汪天宇
2023-03-14
问题内容

编辑:
已经快五年了,我不认为这是要走的路。客户应以正确的数字格式发布数据。对于像React或Angular这样的当前框架,或者具有适当的架构以及错误处理和验证,我认为这几乎不是问题。

但是,如果有人希望展示自己的Json.NET肌肉,请随时检查答案。

我有一个MVC应用程序,并且在其中处理了一些JSON。很简单 我的ModelBinder中有以下简单代码:

return JsonConvert.DeserializeObject(jsonString, bindingContext.ModelType, new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore,
    MissingMemberHandling = MissingMemberHandling.Ignore,
    Formatting = Formatting.None,
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    FloatParseHandling = FloatParseHandling.Decimal
});

它可以完美地工作。

好吧,有点。

假设我有这个课程:

public class MyClass
{
    public decimal MyProp { get; set; }
}

如果我尝试反序列化此json:

"{\"MyProp\": 9888.77}"

当然可以,因为9888.77它是Javascript浮点值。我认为。

但是我的页面上有一个隐藏的金钱输入,使得JSON看起来像这样(对不起我的英语):

"{\"MyProp\": \"9.888,77\" }"

AAAND,它失败。它说的Could not convert string to decimal

好吧,这很公平。它不是JS浮动,而是Convert.ToDecimal("9.888,77")按我想要的方式工作。

我已经在互联网上阅读了一些有关自定义反序列化器的教程,但是对于我为应用程序中的每个类定义自定义反序列化器都是不可行的。

我想要的是在我想反序列化的任何类中,简单地重新定义JSON.Net将字符串转换为十进制属性的方式。我想Convert.ToDecimal在当前转换器不工作时在转换小数的过程中注入该函数。

有办法吗?

我以为有办法做到这一点,所以我稍微修改了代码。

JsonSerializer serializer = new JsonSerializer
{
    NullValueHandling = NullValueHandling.Ignore,
    MissingMemberHandling = MissingMemberHandling.Ignore,
    Formatting = Formatting.None,
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    FloatParseHandling = FloatParseHandling.Decimal,
};



return serializer.Deserialize(new DecimalReader(jsonStr), bindingContext.ModelType);

并创建了这个类:

public class DecimalReader : JsonTextReader
{
    public DecimalReader(string s)
        : base(new StringReader(s))
    {
    }

    public override decimal? ReadAsDecimal()
    {
        try
        {
            return base.ReadAsDecimal();
        }
        catch (Exception)
        {
            if (this.TokenType == JsonToken.String)
            {
                decimal value = 0;

                bool convertible = Decimal.TryParse(this.Value.ToString(), out value);

                if (convertible)
                {
                    return new Nullable<decimal>(value);
                }
                else { throw; }
            }
            else
            {
                throw;
            }
        }
    }
}

但这很丑陋:它只有在崩溃时才执行我想要的, 并且依赖于base.ReadAsDecimal()crashing。它再丑不过了。

并且不起作用Error converting value "1.231,23" to type 'System.Nullable1[System.Decimal]'. Path 'MyProp', line X, position Y.

该值本身正在转换,但也许出于某种原因,它仍试图将字符串“ 1.231,23”放入十进制。

那么,有没有办法正确地做到这一点?


问题答案:

您可以使用这样的自定义JsonConverter类来处理两种格式(JSON数字表示形式和掩码字符串格式)。

class DecimalConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(decimal) || objectType == typeof(decimal?));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Float || token.Type == JTokenType.Integer)
        {
            return token.ToObject<decimal>();
        }
        if (token.Type == JTokenType.String)
        {
            // customize this to suit your needs
            return Decimal.Parse(token.ToString(), 
                   System.Globalization.CultureInfo.GetCultureInfo("es-ES"));
        }
        if (token.Type == JTokenType.Null && objectType == typeof(decimal?))
        {
            return null;
        }
        throw new JsonSerializationException("Unexpected token type: " + 
                                              token.Type.ToString());
    }

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

要将其插入到活页夹中,只需将转换器的一个实例添加到对象Converters列表中JsonSerializerSettings

JsonSerializerSettings settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore,
    MissingMemberHandling = MissingMemberHandling.Ignore,
    Formatting = Formatting.None,
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    Converters = new List<JsonConverter> { new DecimalConverter() }
};


 类似资料:
  • 我想在shell脚本中使用十进制值,但它不起作用。我没有得到十进制值。很少有帖子建议使用linux的“bc”实用程序。但是在我的机器上没有安装“bc”,我没有安装任何实用程序的权限。现在可以在没有bc的情况下处理十进制值了。演示代码-: 输出-:

  • 问题内容: 我想知道的是最有效的代码转换方式(迅速2): 十进制到二进制 二进制到十进制 十进制到十六进制 十六进制到十进制 二进制到十六进制 十六进制到二进制 我已经有了实现该目标的基本且漫长的方法,但是我想找到一种非常有效的方法。 抱歉,问题有点长… 问题答案: 两者和都有带有(基)的初始化程序。结合这些,您可以实现所有转化:

  • Python3 实例 以下代码用于实现十进制转二进制、八进制、十六进制: # -*- coding: UTF-8 -*- # Filename : test.py # author by : www.runoob.com # 获取用户输入十进制数 dec = int(input("输入数字:")) print("十进制数为:", dec) print("转换为二进制为:", bin(dec

  • 问题内容: 如何在JavaScript中将十进制值转换为等效的十六进制值? 问题答案: 使用以下命令将数字转换为十六进制字符串: 并通过以下步骤逆向处理:

  • 问题内容: 如上面的标题。我想从一个十六进制数字 我想转换为。 问题答案:

  • 问题内容: 的十六进制值是,但使用 得到答案 问题答案: 这是由于SQL Server解释没有限定类型的文字的方式。看一下这个