首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在LinqPad中定义的类型不能由Newtonsoft Json序列化程序反序列化。

在LinqPad中定义的类型不能由Newtonsoft Json序列化程序反序列化。
EN

Stack Overflow用户
提问于 2021-07-26 21:39:03
回答 1查看 246关注 0票数 1

我有一个类作为Rebus中的消息类型来发布/订阅,但是当我在LinqPad中尝试概念证明时遇到了一个障碍。如果反序列化异常,我的应用程序接收到的任何消息都会失败。我已经能够将问题缩小到Newtonsoft.JSON包,并提供了一个最小的示例来演示这个问题:

代码语言:javascript
运行
复制
public class MyMessage
{
    public string Name { get; set; } = "";
    public int Number { get; set; }
}

void Main()
{
    var message = new MyMessage { Name = "ABC", Number = 5 };
    
    var defaultSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
    
    var serialized = JsonConvert.SerializeObject(message, defaultSettings);
    
    Console.WriteLine(serialized);

    try
    {
        var deserialized = JsonConvert.DeserializeObject(serialized, message.GetType(), defaultSettings);
        Console.WriteLine(deserialized);
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }
}

如果我在Rider中编译该代码,并将以下内容输出到控制台,则此代码作为控制台应用程序运行良好:

代码语言:javascript
运行
复制
{"$type":"ConsoleApp1.MyMessage, ConsoleApp1","Name":"ABC","Number":5}
ConsoleApp1.MyMessage

在具有带有以下错误消息的LinqPad语句的行的JsonConvert.DeserializeObject 6中,相同的代码会失败:

代码语言:javascript
运行
复制
{"$type":"UserQuery+MyMessage, LINQPadQuery","Name":"ABC","Number":5}
Newtonsoft.Json.JsonSerializationException: Type specified in JSON 'UserQuery+MyMessage, LINQPadQuery, Version=1.0.0.5, Culture=neutral, PublicKeyToken=null' is not compatible with 'UserQuery+MyMessage, LINQPadQuery, Version=1.0.0.61, Culture=neutral, PublicKeyToken=null'. Path '$type', line 1, position 44.
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolveTypeName(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, String qualifiedTypeName)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadMetadataProperties(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue, Object& newValue, String& id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at UserQuery.Main() in C:\Users\arcaa\AppData\Local\Temp\LINQPad6\_dwfnlfnz\tufqxf\LINQPadQuery:line 19

异常消息:Type specified in JSON 'UserQuery+MyMessage, LINQPadQuery, Version=1.0.0.5, Culture=neutral, PublicKeyToken=null' is not compatible with 'UserQuery+MyMessage, LINQPadQuery, Version=1.0.0.61, Culture=neutral, PublicKeyToken=null

看起来,序列化程序试图将字符串反序列化为与作为参数提供的类型(UserQuery+MyMessage, LINQPadQuery, Version=1.0.0.5)不同的版本(UserQuery+MyMessage, LINQPadQuery, Version=1.0.0.61)。有趣的是,JsonConvert.DeserializeObject方法中使用的类型与传递给序列化程序的类型完全相同,代码中只有一个类。

我不知道其他类型的版本是从哪里来的。有没有人知道原因,如果可能的话,如何避免?

编辑:

我还注意到,如果关闭LinqPad并再次打开它,代码就会正常工作。但是,如果然后对代码进行更改(即使我只添加了一个空格),异常就会返回。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-02 02:58:40

最有可能的是,Newtonsoft.Json库中会有一些静态字典,缓存类型信息,键控字符串,如"MyMessage“。当您编辑重新运行的查询时,LINQPad必须重新编译该查询,因此在一个新的DLL中将有一个新的MyMessage版本。但是,Newtonsoft.Json中的静态缓存仍然指向上次执行时使用的旧缓存。

要解决这个问题,您不需要重新启动LINQPad;只需按Shift+F5来清除缓存的进程即可。或者,在查询中添加以下代码:

代码语言:javascript
运行
复制
Util.NewProcess = true;

这告诉LINQPad不要缓存进程以供后续使用。

在> Advanced中也有一个选项,用于永不循环进程。这会带来较小的性能成本;另外,LINQPad的Util.Cache (在执行过程中缓存数据)等方法也无法工作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68536603

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档