簡體   English   中英

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 將其返回給應用程序。 但我有一個問題。 API 將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://stackoverflow.com/a/3139636/11392290https://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 (正零)添加到 db read 的結果中。

例如:

 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 腳本。

例如:

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

謝謝大家

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM