gpt4 book ai didi

c# - JSON.Net 没有为收集项调用 CanConvert?

转载 作者:太空狗 更新时间:2023-10-29 23:40:00 24 4
gpt4 key购买 nike

我有一个转换器,我只想在反序列化时使用它。所以我将 CanWrite 设置为 false,它工作正常并且一切都很好地序列化。然后,Json 字符串包含一个对象图,其中有一个 SantaClauseCollection,其中包含一个 SantaClause 项目数组和一个 $type,表明它们是具体类型 SantaClause。

但是,当它在反序列化时遇到圣诞老人的集合时,它永远不会调用 CanConvert(我有一个断点并看到 SantaClausCollection,按 F5 继续,然后在遇到集合中的项目时应该再次打断点圣诞老人,但事实并非如此)。当它到达 SantaClaus 项目时,它不会尝试调用 CanConvert。它甚至没有为该项目调用 CanConvert 来检查我的转换器是否会处理它,而是尝试自行反序列化它,这不会起作用,因为该类没有默认构造函数,也没有具有属性名称匹配约定的构造函数:

Unable to find a constructor to use for type SantaClaus. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.

我明白为什么会收到此错误,但问题是它表明 Json.net 尝试反序列化对象,而不是调用 CanConvert 来检查我的转换器是否想要处理反序列化。

为什么没有为集合中的每个项目调用 CanConvert?

我的转换器:

class SantaClaus2JsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(SantaClaus);
}

/// <summary>
/// Deserializes a SantaClaus as a SantaClausEx which has a matching constructor that allows it to deserialize naturally.
/// </summary>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize<SantaClausEx>(reader);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}


public override bool CanRead
{
get
{
return true;
}
}

public override bool CanWrite
{
get
{
return false;//We only need this converter when reading.
}
}

}

SantaClausEx 只是继承自SantaClaus 添加了一个构造函数,参数重命名以匹配属性:

class SantaClaus //a third party class I can't modify
{
string Name {get;set;}
public SantaClaus(string santaClauseName) { this.Name = santaClauseName }
}

class SantaClausEx:SantaClaus
{
//provide a constructor with param names matching property names
public SantaClausEx(string name) : base(name)
}

Json.net 无法反序列化 SantaClaus,但它可以反序列化 SantaClauseEx。

我到处都使用 SantaClauseEx 类,它工作得很好,但我想制作一个转换器来自动执行此操作。

这是集合的 Json 的样子:

SantaClausCollection: [
{
$type: "SantaClaus, XMasClasses.NET20"
Name: "St. Bob"
},
{
$type: "SantaClaus, XMasClasses.NET20"
Name: "St. Jim"
}
]

最佳答案

我想您已将转换器添加到设置对象中的 Converters 集合。

我用转换器编写了简单的测试

public class SantaClausJsonTest
{
public SantaClausJsonTest()
{
Settings = new JsonSerializerSettings();
Settings.TypeNameHandling = TypeNameHandling.Objects;
Settings.Converters.Add(new SantaClaus2JsonConverter());
}

private JsonSerializerSettings Settings;

[Fact]
public void SerializeAndDeserialize()
{
var collection = new []
{
new SantaClaus("St. Bob"),
new SantaClaus("St. Jim"),
};

var serialized = JsonConvert.SerializeObject(collection, Settings);

Console.WriteLine(serialized);
Assert.False(string.IsNullOrEmpty(serialized));

var deserialized = JsonConvert.DeserializeObject<SantaClaus[]>(serialized, Settings);

Console.WriteLine(deserialized.GetType().ToString());
Assert.NotNull(deserialized);
Assert.True(deserialized.Any(a => a.Name == "St. Bob"));
Assert.True(deserialized.Any(a => a.Name == "St. Jim"));
}
}

public class SantaClaus
{
public SantaClaus(string santaClauseName)
{
Name = santaClauseName;
}

public string Name { get; private set; }
}

public class SantaClaus2JsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(SantaClaus);
}

/// <summary>
/// Deserializes a SantaClaus as a SantaClausEx which has a matching constructor that allows it to deserialize naturally.
/// </summary>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var name = string.Empty;

while (reader.Read())
{
if (reader.TokenType == JsonToken.String && reader.Path.EndsWith("Name"))
{
name = reader.Value as string;
}
if (reader.TokenType == JsonToken.EndObject)
{
break;
}
}

return Activator.CreateInstance(objectType, name);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotSupportedException();
}


public override bool CanRead
{
get
{
return true;
}
}

public override bool CanWrite
{
get
{
return false;//We only need this converter when reading.
}
}

关于c# - JSON.Net 没有为收集项调用 CanConvert?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14887389/

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