使用System.Text.Json.Serialization解析JSON时出现异常

7

我的样例代码非常简单:

using System.Text.Json.Serialization;
using Newtonsoft.Json;

public class C {
  public C(string PracticeName) { this.PracticeName = PracticeName; }
  public string PracticeName;
}

var x = new C("1");
var json = JsonConvert.SerializeObject(x); // returns "{\"PracticeName\":\"1\"}"

var x1 = JsonConvert.DeserializeObject<C>(json); // correctly builds a C

var x2 = System.Text.Json.Serialization.JsonSerializer.Parse<C>(json);

最后一行产生了异常:

引发异常: 'System.NullReferenceException' in System.Text.Json.dll 对象引用未设置为对象的实例。

我做错了什么?

(请注意,这是在最新的 .NET Core 3 预览版 5 上与最新的 System.Text.Json 4.6.0-preview6.19259.10。)

添加一个无参数构造函数可以避免这个异常,但是我不想/不需要一个无参数构造函数,并且 Json.Net 没有问题地解析它。是否有一种方法可以像 Json.Net 一样使用给定的构造函数进行 System.Text.Json 解析?


4
你尝试过添加无参构造函数吗? - Szymon Tomczyk
1
好的,添加一个无参数构造函数可以防止异常,但是我不想/不需要一个无参数构造函数,而且json.net在没有它的情况下解析得很好。 - kofifus
1
Json.NET没有问题,即使没有无参构造函数,我也找不到任何需要它的文档。 - kofifus
1
@BagusTesa,正如上面所看到的,Json.Net在反序列化我的对象时没有任何问题,由于只有一个构造函数,因此不需要使用[JsonConstructor]属性。 - kofifus
.NET 5 开始,使用 System.Text.Json 反序列化带有参数化构造函数的类型现在可以正常工作,参见 Deserialize anonymous type with System.Text.Json - dbc
显示剩余3条评论
3个回答

18

目前在.NET Core 3.0中,JSON支持仍未完成,似乎只支持无参数构造函数。也许以后会添加该功能。

一个解决方案是为您的序列化模型创建一个无参构造函数,当您想使用.net框架的新Json API时。可能我们根本不应该使用构造函数来传递数据对象,因此我认为这是一种选择而不是解决方法。

如果您正在寻找从旧版本迁移到.NET Core 3.0或者仍然使用Newtonsoft.Json的方法,可以在此处进行查看:

MVC

安装Microsoft.AspNetCore.Mvc.NewtonsoftJson包,并将其注册到您的服务中。

services.AddMvc().AddNewtonsoftJson();

SignalR

安装Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson包。

//Client
new HubConnectionBuilder()
.WithUrl("/chatHub")
.AddNewtonsoftJsonProtocol(...)
.Build();

//Server
services.AddSignalR().AddNewtonsoftJsonProtocol(...);

那样你应该能够在 .Net Core 3.0 中使用 Json.NET 功能。

*我没有安装它,所以无法测试。


对我来说,AddNewtonsoftJson 方法不存在。 - Saeed Neamati
1
你是否安装了上述NuGet包并导入了命名空间Microsoft.Extensions.DependencyInjection?同时请注意,它是IMvcBuilder上的方法,而不是IServiceCollection。您需要像上面@SaeedNeamati所示那样与AddMvc一起使用。 - Christian Gollhardt

2

将PracticeName更改为属性而不是字段。尝试使用无参数构造函数。

我开发了一个快速的控制台程序类。使用Newtonsoft.Json包转换类C1。使用System.Text.Json包解析类C2。

"Original Answer"翻译成中文为"最初的回答"。

using Newtonsoft.Json;

namespace TestJsonParse
{
    class Program
    {
        static void Main(string[] args)
        {
            var c1 = new C1("1");
            var json1 = JsonConvert.SerializeObject(c1); // returns "{\"PracticeName\":\"1\"}"
            var x1 = JsonConvert.DeserializeObject<C1>(json1); // correctly builds a C1

            var c2 = new C2();
            string json2 = "{\"PracticeName\":\"1\"}";
            var x2 = System.Text.Json.Serialization.JsonSerializer.Parse<C2>(json2); // correctly builds a C2
        }

        class C1
        {
            public C1(string PracticeName) { this.PracticeName = PracticeName; }
            public string PracticeName;
        }

        class C2
        {
            public C2() { }
            public string PracticeName { get; set; }
        }
    }
}

你可以发一段代码示例来说明你的建议解决方案吗? - Abra
谢谢,你是在说我不能序列化字段吗?另外我不想要一个空构造函数,我的真实情况涉及到很多类,其中许多类没有空构造函数,但Json.NET对此没有问题。 - kofifus
@kofifus,使用System.Text.Json似乎是这种情况(至少就Parse方法而言)。 - user11400447
你看到我的编辑注释了吗?请不要写“编辑”这个词,它只是噪音。我们已经在编辑历史记录中看到了 ;) - Christian Gollhardt
@ChristianGollhardt 对不起,我还在学习礼仪。 - user11400447
那么您是在说System.Text.Json需要一个无参构造函数,而Json.NET则不需要?您有相关的参考资料吗?谢谢! - kofifus

0

使用 System.Text.Json.Serialization 的 Json 支持非常不稳定。最好使用 NewtonSoft.Json,因为它更加稳定,几乎每个人都在使用它。如果运行控制台应用程序,则可以从终端中的文件夹执行以下操作 enter image description here

您无需指定版本。如果使用 Visual Studio,则使用 Nuget 包管理器安装 Newtonsoft.json。

例如,要从文件中读取 json,可以使用 data.json

{
  "Name":"Logan",
  "Age": 30
  "Books": ["Infinity War", "End Game"]
}

指定您的属性示例

class Person
{
  public string Name{get; set;}
  public int Age{get; set;}
  public IList<string> Books{get; set;}
}

然后从您希望访问JSON数据的类中执行以下操作

string fileContent = System.IO.File.ReadAllText(@"./data.json");
Person person = Newtonsoft.Json.JsonConverter.DeserializeObject<Person>(fileContent);

测试一下

Console.WriteLine($"Hi {person.Name} you are {person.Age} today read {person.Books[0]}");

欲了解更多信息,请访问https://www.newtonsoft.com/json/help/html/DeserializeObject.htm


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