gpt4 book ai didi

C# JSON 反序列化 System.NotSupportedException

转载 作者:行者123 更新时间:2023-12-05 01:31:41 25 4
gpt4 key购买 nike

我一直在做一个需要通过 JSON 文件保存和加载数据的项目。此 JSON 文件包含其他对象的各种列表。但是,当我继续反序列化文件时,会发生这种情况:

System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported.

负责反序列化的代码如下:

        public void LoadFromJson() {

int userCount = File.ReadAllLines(folder + "/users").Length;
int shopCount = File.ReadAllLines(folder + "/shops").Length;
using (FileStream fileUsers = File.Open(folder + "/users", FileMode.Open, FileAccess.Read)) {
StreamReader srUser = new StreamReader(fileUsers);
for(int i=0; i<userCount; i++){
ListOfUsers.Add(JsonSerializer.Deserialize<User>(srUser.ReadLine()));
}
srUser.Close();
fileUsers.Close();
}

using (FileStream fileShops = File.Open(folder + "/shops", FileMode.Open, FileAccess.Read)){
StreamReader srShops = new StreamReader(fileShops);
for(int i=0; i<shopCount; i++){
ListOfShops.Add(JsonSerializer.Deserialize<Shop>(srShops.ReadLine()));
}
srShops.Close();
fileShops.Close();
}

}

我正在尝试反序列化的类

    public abstract class Shop{

public List<Sellable> ShopList { get; set; }
public int TotalValue { get; set; }
public string shopName { get; set; }

public Shop(List<Sellable> list, string shopname){
ShopList = list;
shopName = shopname;
}

public abstract bool AddToShop(Sellable item);
public abstract bool RemoveFromShop(string item);
public abstract int GetValue(string name);
public abstract string PrintShop();

}

public abstract class Furniture : Sellable{
public int Space { get; set; }
public Conditions Condition { get; set; }
public Materials Material { get; set; }

[JsonConstructorAttribute]
public Furniture(int val, int spc, string nm, Conditions condition, Materials material) : base (val, nm){
Space = spc;
Condition = condition;
Material = material;
}

}

public abstract class Sellable{
public int Value { get; set; }
public string Name { get; set; }

[JsonConstructorAttribute]
public Sellable(int val, string name){
Value = val;
Name = name;
}

Json转换器

    public class SellableConverter : JsonConverter<Sellable>{ 

public enum Type{
Sellable,
Furniture,
Wearable,

}

public override Sellable Read(ref Utf8JsonReader reader, System.Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject) throw new JsonException();

if (!reader.Read()
|| reader.TokenType != JsonTokenType.PropertyName
|| reader.GetString() != "Type") throw new JsonException();

if (!reader.Read() || reader.TokenType != JsonTokenType.Number) throw new JsonException();

Sellable baseClass;
Type typeDiscriminator = (Type)reader.GetInt32();
switch (typeDiscriminator)
{
case Type.Furniture:
if (!reader.Read() || reader.GetString() != "TypeValue") throw new JsonException();
if (!reader.Read() || reader.TokenType != JsonTokenType.StartObject) throw new JsonException();
baseClass = (Furniture.Furniture)JsonSerializer.Deserialize(ref reader, typeof(Furniture.Furniture), options);
break;
case Type.Wearable:
if (!reader.Read() || reader.GetString() != "TypeValue") throw new JsonException();
if (!reader.Read() || reader.TokenType != JsonTokenType.StartObject) throw new JsonException();
baseClass = (Wearable)JsonSerializer.Deserialize(ref reader, typeof(Wearable), options);
break;
case Type.Sellable:
if (!reader.Read() || reader.GetString() != "TypeValue") throw new JsonException();
if (!reader.Read() || reader.TokenType != JsonTokenType.StartObject) throw new JsonException();
baseClass = (Sellable)JsonSerializer.Deserialize(ref reader, typeof(Sellable));
break;
default:
throw new NotSupportedException();
}

if (!reader.Read() || reader.TokenType != JsonTokenType.EndObject) throw new JsonException();

return baseClass;
}

public override void Write(Utf8JsonWriter writer, Sellable value, JsonSerializerOptions options)
{
writer.WriteStartObject();

if (value is Furniture.Furniture derivedA)
{
writer.WriteNumber("TypeDiscriminator", (int)Type.Furniture);
writer.WritePropertyName("TypeValue");
JsonSerializer.Serialize(writer, derivedA, options);
}
else if (value is Wearable derivedB)
{
writer.WriteNumber("TypeDiscriminator", (int)Type.Wearable);
writer.WritePropertyName("TypeValue");
JsonSerializer.Serialize(writer, derivedB, options);
}
else if (value is Sellable baseClass)
{
writer.WriteNumber("TypeDiscriminator", (int)Type.Sellable);
writer.WritePropertyName("TypeValue");
JsonSerializer.Serialize(writer, baseClass);
}
else throw new NotSupportedException();

writer.WriteEndObject();
}
}

SaveToJson 方法:

        public void SaveToJson(){

FileStream fileUsers;
FileStream fileShops;

if(!(File.Exists(folder + "/users"))) fileUsers = File.Create(folder + "/users");
else fileUsers = File.OpenWrite(folder + "/users");
if(!(File.Exists(folder + "/shops"))) fileShops = File.Create(folder + "/shops");
else fileShops = File.OpenWrite(folder + "/shops");

StreamWriter srUser = new StreamWriter(fileUsers);
StreamWriter srShop = new StreamWriter(fileShops);

var serializeOptions = new JsonSerializerOptions();
serializeOptions.Converters.Add(new SellableConverter());

for(int i=0; i<ListOfUsers.Count; i++){
srUser.WriteLine(JsonSerializer.Serialize<User>(ListOfUsers[i]), serializeOptions);
Console.WriteLine("Debug: " + "\n" + "Object: " + ListOfUsers[i] + "\n" + "Json: " + JsonSerializer.Serialize<User>(ListOfUsers[i]));
}
for(int i=0; i<ListOfShops.Count; i++){
srShop.WriteLine(JsonSerializer.Serialize<Shop>(ListOfShops[i]), serializeOptions);
Console.WriteLine("Debug: " + "\n" + "Object: " + ListOfShops[i] + "\n" + "Json: " + JsonSerializer.Serialize<Shop>(ListOfShops[i]));
}

srUser.Close();
fileUsers.Close();
srShop.Close();
fileShops.Close();

}

我该如何解决?提前致谢! :)

编辑:我添加了我试图反序列化的类。如果我没有提供足够的细节或犯了愚蠢的错误,我深表歉意,我还是一名学生,第一次尝试搞砸这些事情中的大部分

最佳答案

您的异常说明您不能反序列化没有默认(无参数)构造函数的类。

您正在反序列化的类,或作为该类的属性包含的其中一个类,有一个接受参数的构造函数,但也没有默认构造函数。

反序列化器无法创建该类的实例,因为它没有传递给该构造函数的参数。

如果没有看到您要反序列化的类的定义,我无法提供进一步的帮助。

编辑:看起来 Newtonsoft.Json 足以提供一些您几乎可以正确使用的属性来解决此问题。 JsonConstructorAttribute 将匹配使用构造函数参数反序列化的序列化字符串的属性,前提是名称匹配(忽略大小写)。

[JsonConstructor]
public Sellable(int value, string name){
Value = value;
Name = name;
}

感谢Brian Rogers' answer为了获得线索,我需要找到相关文档!

关于C# JSON 反序列化 System.NotSupportedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65963843/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com