JSON值无法转换为System.Int32。

85

我想向我的Web API发送对象的数据。该API接受一个类参数,其中属性的类型是int和string。

这是我的类:

public class deneme
{
   public int ID { get; set; }
   public int sayi { get; set; }
   public int reqem { get; set; }
   public string yazi { get; set; }
}
这是我的JSON对象:

This is my JSON object:

{
   "id":0,
   "sayi":"9",
   "reqem":8,
   "yazi":"sss"
}

我希望API能够将属性"sayi"读取为整数,但由于无法这样做,它会产生错误:

The JSON value could not be converted to System.Int32. Path: $.sayi

我该如何解决这个问题?


3
无法将字符串赋值给整数变量,需将字符串转换为整数类型。 - FrV
3
必须将其设为 "sayi": 9(不带引号),或者您必须将其绑定到字符串而不是整数,并自行进行转换。没有其他选择。 - Chris Pratt
5
我更新 ASP.NET Core 从 2.2 到 3.0 之前,当我输入“9”时它是有效的。但在升级后,它不再有效。请帮我翻译这句话。 - ali suleymanli
这也可能是当数字值高于或低于int范围时的错误消息,可能需要将其定义为long、float、double等。只是提供给其他在谷歌上搜索的人的信息。 - alexfyren
它从.NET 5开始得到支持,请查看答案https://dev59.com/n1MH5IYBdhLWcg3w6VUv#67153702 - HRKoder
请看这里的解决方案<a href="https://dev59.com/JVMH5IYBdhLWcg3woQnQ#74913526">here</a>。 - Mahmmoud Kinawy
9个回答

116

对于Asp.Net Core 3.0,它使用System.Text.Json进行序列化和反序列化。

如果要使用旧的行为,您可以通过引用Json.NET支持来在ASP.NET Core 3.0项目中使用Json.NET。

简短回答:

  1. 安装预览版本的Microsoft.AspNetCore.Mvc.NewtonsoftJson
  2. 将代码更改为services.AddControllers().AddNewtonsoftJson();

2
太好了,谢谢。问题是,为什么微软不能使用最常下载的NuGet包... - Adriaan Davel
2
它的效率和性能不如人意。Newtonsoft是一个很棒的包,因为它涵盖了各种各样的用例。随着这么多用例的出现,也带来了性能开销。Microsoft的则非常专注于自己的产品,它以aspnetcore的性能驱动为目标。 - Johnathon Sullinger
2
我只能通过这种方式才能正确反序列化我的对象。由于某种原因,Microsoft.AspNetCore.Mvc.NewtonsoftJson在包管理器中没有显示出来,必须使用Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson -Version 3.0.0手动安装它。它会指示该软件包可以更新为3.1.0版本,但需要net core 3.1,而该版本仍处于预发布阶段。写下这篇评论希望能帮助遇到此问题的其他人! - Zulukas
谢谢。我认为在默认设置中不应该发生这种错误,使用默认设置提交 { num: 0.2 } 到服务器时出现这种错误是不正常的。 - Vitaly Leskiv

36
从.NET 5开始,有一个选项可以反序列化作为JSON字符串表示的数字,而不是抛出异常。
using System.Text.Json;
using System.Text.Json.Serialization;

var options = new JsonSerializerOptions()
{
     NumberHandling = JsonNumberHandling.AllowReadingFromString |
     JsonNumberHandling.WriteAsString
};

// serialize
string denemeJson = JsonSerializer.Serialize<Deneme>(deneme, options);

// deserialize
Deneme denemeDeserialized = JsonSerializer.Deserialize<Deneme>(denemeJson, options);

JsonNumberHandling这个名称在当前上下文中不存在。 - Jhon Hernández
2
@JhonHernández 你确定你正在使用 .NET 5 吗? - HRKoder
1
点赞。这是一个 .NET 5 项目的答案。 - J Weezy
你能使用此设置或类似设置将浮点数如1800.0存储到整数属性中吗? - Oliver Nilsen

29

首先,您应该创建一个JsonConverter

using System;
using System.Buffers;
using System.Buffers.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace sample_22_backend.Converters
{
    public class IntToStringConverter : JsonConverter<int>
    {
        public override int Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.String)
            {
                ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
                if (Utf8Parser.TryParse(span, out int number, out int bytesConsumed) && span.Length == bytesConsumed)
                {
                    return number;
                }

                if (int.TryParse(reader.GetString(), out number))
                {
                    return number;
                }
            }

            return reader.GetInt32();
        }

        public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString());
        }
    }
}

然后在您的模型属性上以这种方式使用它:

[JsonConverter(typeof(IntToStringConverter))]
public int GenreId { set; get; }

或者你可以全局添加它:

services.AddControllers()
        .AddJsonOptions(options => 
                options.JsonSerializerOptions.Converters.Add(new IntToStringConverter()));

2
应该是StringToInt转换器吧? - Jay Jay Jay
有没有非自定义的方法来做这件事?我认为他们会修复这个问题并允许人们传递未加引号的整数。这破坏了许多现有API。我认为这是最好的答案,因为我觉得使用Newtonsoft不是朝着正确的方向前进。 - Dan Parker
这已经被安排在下一个 .NET 版本中:https://github.com/dotnet/runtime/issues/30255 - VahidN
当调用Deserialize方法时,您还可以将此作为JsonSerializerOptions的一部分传递,如下所示:var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, Converters = { new API.Helpers.StringToGuidConverter() } };StreamReader reader = new StreamReader(HttpContext.Current.Request.InputStream); string json = reader.ReadToEnd(); return JsonSerializer.Deserialize<T>(json, options); - Sergio A.

10
在.NET CORE 3.X中,序列化/反序列化过程使用System.Text.Json而不是Newtonsoft Json。Edward的回答对我来说并不完全有效:
  1. 从Nuget Manager安装Microsoft.AspNetCore.Mvc.NewtonsoftJson无法使步骤2编译。
  2. 是的,在Startup中添加services.AddControllers().AddNewtonsoftJson()会出现错误,AddNewtonsoftJson()未被识别。
至少对我来说是这样的。
作为解决方法,请卸载您在步骤1中安装的内容。在程序包管理器控制台中运行:Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson -Version 3.0.0-preview8.19405.7。这对我有效。

3
更好地将值解析为 Integer,并从客户端应用程序向服务器端应用程序发送数据,这对我有帮助。 编码愉快!
{
  "id":parseInt(0),
  "sayi":parseInt(9),
  "reqem":parseInt(8),
  "yazi":"sss"
 }

2

顺便说一下,我认为我已经实现了建议的答案,因为我在我的Program.cs中有以下内容

builder.Services.AddControllersWithViews().AddJsonOptions(opt =>
                {
                    opt.JsonSerializerOptions.PropertyNamingPolicy = null;
                    opt.JsonSerializerOptions.AllowTrailingCommas = true;
                    opt.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString |
                        JsonNumberHandling.WriteAsString;                    
                    opt.JsonSerializerOptions.IncludeFields = true;
                });

由于某些原因,我的控制器忽略了它,我不知道为什么,在它能够工作之前,我不得不实现HRKoder建议的修复方法。


1

还有一种方法:只需创建一个DTO,使用字符串类型来表示数字类型,并将其转换为控制器或所需的类型。


1
在 JavaScript 模型中,请确保您的值已格式化为 parseFloat()。

-3

在 .net core 中可能会遇到这个问题,您可以将数据类型从 int 更改为 int64


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接