草庐IT

关于 c#:Can’t cast objects from Dictionary after using json.net deserialization

codeneng 2023-03-28 原文

Can't cast objects from Dictionary after using json.net deserialization

我对反序列化字典有疑问。我无法将 Dictionary 中的对象转换为我的类型 Remiza...我正在使用 Json.net,我可以看到 Dictionary 中的对象是 JObject 而不是 Object,我不能将它们转换为我的类型。这是我的序列化/反序列化代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    private static Dictionary<Type, List<Object>> _ekstensje = new Dictionary<Type, List<Object>>();

    public static void SerializeDictionary()
        {
            string json = JsonConvert.SerializeObject(_ekstensje);
            System.IO.StreamWriter file = new System.IO.StreamWriter(@"c:\\tmp\\dictionary.json");
            file.WriteLine(json);

            file.Close();
        }

        public static void DeserializeDictionary()
        {
            string json;
            System.IO.StreamReader file = new System.IO.StreamReader(@"c:\\tmp\\dictionary.json");
            json = file.ReadToEnd();

            file.Close();
            _ekstensje = JsonConvert.DeserializeObject<Dictionary<Type, List<Object>>>(json);//Deserializacja Dictionary
            Debug.WriteLine(_ekstensje);
        }

        public static List<Object> GetEkstensja(Type className)
        {
            List<Object> list = _ekstensje[className];
            return list;
        }

执行:

1
2
3
4
5
6
7
        ObjectPlus.DeserializeDictionary();
        List<Object> list = ObjectPlus.GetEkstensja(typeof(Remiza));
        foreach (Object o in list)
        {
            Remiza r = (Remiza) o;
            listaRemiz.Add(r);
        }

我的问题是在投射到"Remiza"时出现异常:

1
An exception of type 'System.InvalidCastException' occurred in Osek_MAS_WPF.exe but was not handled in user code. Additional information: Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'Osek_MAS_WPF.Remiza'.

感谢您的帮助!

  • 如果您使用对象类型的字典,那么 JSON.net 可以为您提供的最好的就是 Jobject。您没有指定它应该尝试解析的类型,因此您将无法从中获得更具体的类。您可以编写自定义反序列化器或在其中放置强类型。或者将其保留为 Jobject 并手动解析条目。
  • 好的,那么如何将这些条目从 JObject 手动解析为我的类型?这正是我想要达到的目标。


这应该允许您将 JObect 转换为您的 Remiza 类型。

1
2
3
4
5
6
7
ObjectPlus.DeserializeDictionary();
    List<Object> list = ObjectPlus.GetEkstensja(typeof(Remiza));
    foreach (Object o in list)
    {
        Remiza r = o.ToObject<Remiza>();
        listaRemiz.Add(r);
    }

我从下面链接的 stackoverflow 答案中得到了这个。如果我放的东西不起作用,请查看链接,它应该可以帮助您运行它。

https://stackoverflow.com/a/10221594/634769

  • 不幸的是,在我的 Class Remiza 中,我列出了 Person 是抽象类的 Person 列表,它无法正常工作,因为它无法创建 Person 的实例...... Newtonsoft.Json.dll 中发生了"Newtonsoft.Json.JsonSerializationException"类型的异常,但是未在用户代码中处理附加信息:无法创建 Osek_MAS_WPF.Osoba 类型的实例。类型是接口或抽象类,不能实例化。我开始认为序列化不是保持类扩展的最佳解决方案......当有那种关联时,它就无法正常工作,正如我们所看到的......
  • 在使用 ToObject 之前,他必须将对象实际转换为 JObject。 Remiza r = ((JObject)o).ToObject<Remiza>();


为了使用 Json.NET 成功序列化和反序列化多态类型,您需要设置 TypeNameHandling = TypeNameHandling.Auto,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class ObjectPlus
{
    // Replace with whatever file name is appropriate.  My computer doesn't have a"c:\\tmp" directory.
    static string JsonFileName { get { return Path.Combine(Path.GetTempPath(),"dictionary.json"); } }

    static JsonSerializerSettings JsonSettings { get { return new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, Formatting = Formatting.Indented }; } }

    private static Dictionary<Type, List<Object>> _ekstensje = new Dictionary<Type, List<Object>>();

    public static void SerializeDictionary()
    {
        var path = JsonFileName;

        using (var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
        using (var writer = new StreamWriter(stream))
        {
            var serializer = JsonSerializer.CreateDefault(JsonSettings);
            serializer.Serialize(writer, _ekstensje);
        }
    }

    public static void DeserializeDictionary()
    {
        var path = JsonFileName;
        try
        {
            using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = new StreamReader(stream))
            using (var jsonReader = new JsonTextReader(reader))
            {
                var serializer = JsonSerializer.CreateDefault(JsonSettings);
                _ekstensje = serializer.Deserialize<Dictionary<Type, List<Object>>>(jsonReader);
            }
        }
        catch (FileNotFoundException)
        {
            // File was not created yet, dictionary should be empty.
            _ekstensje.Clear();
        }
    }

    public static List<Object> GetEkstensja(Type className)
    {
        List<Object> list = _ekstensje[className];
        return list;
    }

    public static void AddEkstensja< T >(T obj)
    {
        List<Object> list;
        if (!_ekstensje.TryGetValue(obj.GetType(), out list))
            list = _ekstensje[obj.GetType()] = new List<object>();
        list.Add(obj);
    }

    internal static string ShowJsonContents()
    {
        if (!File.Exists(JsonFileName))
            return string.Empty;
        return File.ReadAllText(JsonFileName);
    }
}

您现在应该能够在字典包含 Remiza.

的实例时对其进行序列化和反序列化

这适用于序列化为对象或集合的类型。但是,如果您的字典包含序列化为 JSON 原语的类型 - 例如 enumlong - 您可能需要将它们封装在类型package器中,沿着 Deserialize specific enum into system.enum in Json .Net.

(顺便说一句,您的 _ekstensje 字典不是线程安全的。)

有关关于 c#:Can’t cast objects from Dictionary after using json.net deserialization的更多相关文章

  1. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  2. ruby CSV : How can I read a tab-delimited file? - 2

    CSV.open(name,"r").eachdo|row|putsrowend我得到以下错误:CSV::MalformedCSVErrorUnquotedfieldsdonotallow\ror\n文件名是一个.txt制表符分隔文件。我是专门做的。我有一个.csv文件,我转到excel,并将文件保存为.txt制表符分隔的文件。所以它是制表符分隔的。CSV.open不应该能够读取制表符分隔的文件吗? 最佳答案 尝试像这样指定字段分隔符:CSV.open("name","r",{:col_sep=>"\t"}).eachdo|row|

  3. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  4. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  7. ruby-on-rails - 关于 Ruby 的一般问题 - 2

    我在我的rails应用程序中安装了来自github.com的acts_as_versioned插件,但有一段代码我不完全理解,我希望有人能帮我解决这个问题class_eval我知道block内的方法(或任何它是什么)被定义为类内的实例方法,但我在插件的任何地方都找不到定义为常量的CLASS_METHODS,而且我也不确定是什么here,并且有问题的代码从lib/acts_as_versioned.rb的第199行开始。如果有人愿意告诉我这里的内幕,我将不胜感激。谢谢-C 最佳答案 这是一个异端。http://en.wikipedia

  8. ruby - 混帐 & ruby : How can I unset the GIT_DIR variable from inside a ruby script? - 2

    我编写了一个非常简单的“部署”脚本,作为我的裸git存储库中的post-updateHook运行。变量如下livedomain=~/mydomain.comstagingdomain=~/stage.mydomain.comgitrepolocation=~/git.mydomain.com/thisrepo.git(bare)core=~/git.mydomain.com/thisrepo.gitcore==addedremoteintoeachlive&stagegitslive和stage都初始化了gitrepos(非裸),我已经将我的裸仓库作为远程添加到它们中的每一个(名为co

  9. ruby-on-rails - 在 Ruby 或 Rails 中,hash.merge({ :order => 'asc' }) can return a new hash with a new key. 什么可以返回带有已删除键的新散列? - 2

    在Ruby(或Rails)中,我们可以做到new_params=params.merge({:order=>'asc'})现在new_params是一个带有添加键:order的散列。但是是否有一行可以返回带有已删除key的散列?线路new_params=params.delete(:order)不会工作,因为delete方法返回值,仅此而已。我们必须分3步完成吗?tmp_params=paramstmp_params.delete(:order)returntmp_params有没有更好的方法?因为我想做一个new_params=(params[:order].blank?||para

  10. ruby - 我怎样才能更好地了解/了解更多关于 Ruby 的知识? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我最近开始学习Ruby,这是我的第一门编程语言。我对语法感到满意,并且我已经完成了许多只教授相同基础知识的教程。我已经写了一些小程序(包括我自己的数组排序方法,在有人告诉我谷歌“冒泡排序”之前我认为它非常聪明),但我觉得我需要尝试更大更难的东西来理解更多关于Ruby.关于如何执行此操作的任何想法?

随机推荐