NewtonSoft JsonConvert.SerializeObject 确实将零序列化为负零(0 序列化为 -0.0)

NewtonSoft JsonConvert.SerializeObject does serialize zero to negative zero ( 0 serialized like as -0.0 )

我有一个 ASP.NET 5 Web API 项目。我使用 MsSql 2016 数据库。我从数据库中获取数据并通过 API return 将其发送到应用程序。但我有一个问题。 API returns 0 喜欢 -0.0 (负零)

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<MyDbContext>(options => options.UseSqlServer(ConfigManager.ConnectionString));

    services.AddControllersWithViews().AddNewtonsoftJson();

    services.AddSwaggerGen(c =>
    {
        c.OperationFilter<AddXUserIdRequiredHeaderParameter>();
        //c.OperationFilter<AddXLanguageHeaderParameter>();
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "MyManagerWS", Version = "v1" });

        // Set the comments path for the swagger json and ui.
        var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        c.IncludeXmlComments(xmlPath);
    });
}
public class DbHelper {

        public static GetDataOutput GetData(int userId, GetDataInput input)
        {
            var result = new ReportItemStockDataResponse();

            string sqlQuery = @"SELECT  ItemId,
                                        ItemName,
                                        ItemCode,
                                        Barcode,
                                        ActualAmount,
                                        UnitName,
                                        RealAmount,
                                        SpecialAmount,
                                        ActualAmountWithSecondUnit,
                                        RealAmountWithSecondUnit,
                                        SpecialAmountWithSecondUnit,
                                        SecondUnitName,
                                FROM
                                MyTable";
            try
            {
                using (var connDb = new SqlConnection(_connectionString))
                {
                    connDb.Open();
                    using (var command = connDb.CreateCommand())
                    {
                        using (var dr = command.ExecuteReader())
                        {
                            while (dr.Read())
                            {
                                result.ItemStockLines.Add(
                                    new ReportItemStockDataResponse.ItemStock()
                                    {
                                           ItemId = Convert.ToInt32(dr["ItemId"]),
                                           ItemName = dr["ItemName"].ToString(),
                                           ItemCode = dr["ItemCode"].ToString(),
                                           Barcode = dr["Barcode"].ToString(),
                                           ActualAmount = Convert.ToDouble(dr["ActualAmount"]),
                                           UnitName = dr["UnitName"].ToString(),
                                           RealAmount = Convert.ToDouble(dr["RealAmount"]),
                                           SpecialAmount = Convert.ToDouble(dr["SpecialAmount"]),
                                           ActualAmountWithSecondUnit = Convert.ToDouble(dr["ActualAmountWithSecondUnit"]),
                                           RealAmountWithSecondUnit = Convert.ToDouble(dr["RealAmountWithSecondUnit"]),
                                           SpecialAmountWithSecondUnit = Convert.ToDouble(dr["SpecialAmountWithSecondUnit"]),
                                           SecondUnitName = dr["SecondUnitName"].ToString(),
                                    });
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Error");
                result = null;
            }

            return result;
        }
}
var result=DbHelper.GetData();
var serializedResult = JsonConvert.SerializeObject(result);

序列化结果如下:

{
    "itemStockLines": [
        {
            "itemId": 111222333,
            "itemCode": "Test code",
            "itemName": "Test item",
            "barcode": "",
            "actualAmount": -0.0,
            "realAmount": -0.0,
            "specialAmount": -0.0,
            "unitName": "ADET",
            "secondUnitName": "QUTU",
            "actualAmountWithSecondUnit": -0.0,
            "realAmountWithSecondUnit": -0.0,
            "specialAmountWithSecondUnit": -0.0
        }
     ]
}

actualAmountrealAmountspecialAmountactualAmountWithSecondUnitrealAmountWithSecondUnitspecialAmountWithSecondUnit 在 C# 和 DB 中为零。

注意: 这些是 C# 中的双变量

Microsoft.AspNetCore.Mvc.NewtonsoftJson版本为5.0.3

感谢您的帮助

我不期待任何赞成票或反对票。仅供参考。

谁想了解更多关于符号零的信息我可以推荐 和 https://en.wikipedia.org/wiki/Signed_zero

我做了这个测试只是为了记录。对我来说,结果看起来很有趣。我反序列化了 PO json 并使用 NewtonsoftJson 再次对其进行了序列化。所有负零双打仍然是负数

var jsonDeserealized=JsonConvert.DeserializeObject<Root>(json);
var jsonReversed=JsonConvert.SerializeObject(jsonDeserealized);

结果

{
  "itemStockLines": [
    {
      "itemId": 111222333,
      "itemCode": "Test code",
      "itemName": "Test item",
      "barcode": "",
      "actualAmount": -0.0,
      "realAmount": -0.0,
      "specialAmount": -0.0,
      "unitName": "ADET",
      "secondUnitName": "QUTU",
      "actualAmountWithSecondUnit": -0.0,
      "realAmountWithSecondUnit": -0.0,
      "specialAmountWithSecondUnit": -0.0
    }
  ]
}

public class ItemStockLine
{
    public int itemId { get; set; }
    public string itemCode { get; set; }
    public string itemName { get; set; }
    public string barcode { get; set; }
    public double actualAmount { get; set; }
    public double realAmount { get; set; }
    public double specialAmount { get; set; }
    public string unitName { get; set; }
    public string secondUnitName { get; set; }
    public double actualAmountWithSecondUnit { get; set; }
    public double realAmountWithSecondUnit { get; set; }
    public double specialAmountWithSecondUnit { get; set; }
}

public class Root
{
    public List<ItemStockLine> itemStockLines { get; set; }
}

如果你想从负零转换为正整数,你可以使用这个代码

private double ConvertToDouble( string val)
{
    var value=Convert.ToDouble(val);
    return IsNegativeZero(value)? 0.0d : value;
}
private bool IsNegativeZero(double x)
{
    return x == 0.0 && double.IsNegativeInfinity(1.0 / x);
}

测试

var stringValue= "-0";
var value = ConvertToDouble(stringValue); // value= 0

你可以这样用

 SpecialAmount = ConvertToDouble(dr["SpecialAmount"]),

我研究了几天这个问题并找到了解决这个问题的方法。

我只将 0.0(正零)添加到数据库读取的结果中。

例如:

 ActualAmount = Convert.ToDouble(dr["ActualAmount"]) + 0.0

我测试了这个解决方案,它运行良好:

using Newtonsoft.Json;
using System;

var str = "-0";

var double1 = Convert.ToDouble(str);

var double2 = Convert.ToDouble(str) + 0.0;

var serializedDouble1 = JsonConvert.SerializeObject(double1);

var serializedDouble2 = JsonConvert.SerializeObject(double2);

Console.WriteLine($"serializedDouble1: {serializedDouble1}");
Console.WriteLine($"serializedDouble2: {serializedDouble2}");

结果:

注意:此解决方案的最佳方法是将插入数据的SQL脚本更改为table。

例如:

INSERT INTO MyTable(ActualAmount) VALUES(@actualAmount + 0.0)

感谢大家