来自包含双精度数字的 Json 帖子的错误 400(错误请求)

Posted

技术标签:

【中文标题】来自包含双精度数字的 Json 帖子的错误 400(错误请求)【英文标题】:Error 400 (Bad Request) from Json post containing double-precision numbers 【发布时间】:2020-09-26 12:48:27 【问题描述】:

我正在向将结果数据存储在数据库中的服务器发送常规帖子。很多时候,服务器返回 400 错误,这似乎意味着帖子格式错误。但是我可以告诉(从正确的数据存储在数据库中的事实)有时服务器已经接受了数据。 Json 非常简单,每次都几乎相同,例如

"latitude":50.2905,"longitude":5.04548,"recorded_at":"20200925 21:07:31","owner":1。

有时它会毫无错误地被接受。如果数据通过 WiFi/宽带或通过 4G 发送,则会发生错误。 发送数据的(Xamarin)代码如下:

    private string UploadResult(WebClient client, double lat, double lng, DateTime t)
    
        client.Headers[HttpRequestHeader.ContentType] = "application/json";

        lat = Math.Round(lat, 5);
        lng = Math.Round(lng, 5);
        json = string.Format("\"latitude\":0,\"longitude\":1,\"recorded_at\":\"2\",\"owner\":3",
            lat, lng, DBTime(t), MyLocation.owner);
        Uri uri = new Uri(UrlBase.urlBase + "SaveLocation");
        string result = client.UploadString(uri, json);
        return result;
    

我无权访问服务器来调试它,只能查看数据库条目。这是一个将数据存储在 MSSQL 数据库中的 WCF 服务,经纬度以十进制 (10,6) 形式存储。我相当确定问题是最近才出现的,即使相关代码没有更改 - 我之前没有收到这些错误(无论如何都不明显)。

我在这里做了很多搜索并尝试了很多代码更改,所有这些都没有效果。我在使用不同版本的 Visual Stuio、Xamarin 和 android API 级别时遇到了同样的问题。

最终我尝试在发布之前降低经纬度的精度,即

        lat = Math.Round(lat, 1);
        lng = Math.Round(lng, 1);

和 Bingo!,一切都很好(当然除了我的数据库的准确性)。有 2 位或更多小数位会导致错误返回。

很明显,可以将服务器代码更改为仅接受整数,并以不同的方式发送数据,但这会很棘手。我可以在客户端代码中更改什么来解决这个问题?

[稍后] 我尝试为十进制数字添加正确的字符串格式

        json = string.Format("\"latitude\":0:0.0000,\"longitude\":1:0.0000,\"recorded_at\":\"2\",\"owner\":3", ....
 

但这并没有什么不同。有趣的是,我还尝试将数字作为字符串发送

        json = string.Format("\"latitude\":\"0\",\"longitude\":\"1\",\"recorded_at\":\"2\",\"owner\":3", ......
     

这同样被接受,但错误频率相同。据我了解,数字数据应该作为字符串被拒绝。

【问题讨论】:

【参考方案1】:

通过将 WebClient 更改为 HttpClient 来解决它。我知道 WebClient 是老技术,但我很早以前就编写了原始代码,它确实可以正常工作。

    private async Task<HttpResponseMessage> UploadResult(double lat, double lng, DateTime t)
    
        lat = Math.Round(lat, 5);
        lng = Math.Round(lng, 5);
        using (HttpClient httpClient = new HttpClient())
        
            string json = string.Format("\"latitude\":0:0.00000,\"longitude\":1:0.00000,\"recorded_at\":\"2\",\"owner\":3",
            lat, lng, DBTime(t), Location.owner);
            var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
            HttpResponseMessage response = null;
            Uri uri = new Uri(UrlBase.urlBase + "SaveLocation");
            try
            
               response = await httpClient.PostAsync(uri, content);
            
            catch (Exception ex)
            
                if (response == null)
                
                    response = new HttpResponseMessage();
                
                response.StatusCode = HttpStatusCode.InternalServerError;
                response.ReasonPhrase = string.Format("Post failed: 0", ex.Message);

            
            return response;

        
    

也需要用await调用这个函数。

【讨论】:

感谢分享。不要忘记接受答案。

以上是关于来自包含双精度数字的 Json 帖子的错误 400(错误请求)的主要内容,如果未能解决你的问题,请参考以下文章

Json.NET 用最少的小数位序列化浮点/双精度,即没有多余的“.0”?

为啥我不能将数字转换为双精度数?

如何避免以科学记数法表示的双精度数和数字的字符串到数字转换?

为啥我在 AngularJs 帖子中收到 400 个错误请求?

将字符串转换为整数或双精度数

序列化包含转义(反斜杠和双引号)的 JSON 字符串 Swift 返回格式错误的对象