【问题标题】:How does Dictionary<string, object> know the type of the value?Dictionary<string, object> 如何知道值的类型?
【发布时间】:2017-04-26 21:37:29
【问题描述】:

考虑这段代码:

JObject obj = JObject.Parse(json);

Dictionary<string,object> dict = new Dictionary<string, object>();

List<string> parameters = new List<string>{"Car", "Truck", "Van"};

foreach (var p in parameters)
{
    JToken token = obj.SelectToken(string.Format("$.results[?(@.paramName == '{0}')]['value']", p));
    dict[p] = token.Value<object>();
}

string jsonOutput = JsonConvert.SerializeObject(dict);

其中json 部分包含:

{
    "paramName": "Car",
    "value": 68.107
},
{
    "paramName": "Truck",
    "value": 48.451
},
{
    "paramName": "Van",
    "value": 798300
}

在调试时,我检查了字典,发现这些值不是object 类型,而是像integerfloat 这样的实际数字类型。由于字典被声明为Dictionary&lt;string, object&gt; dict = new Dictionary&lt;string, object&gt;();,我希望这些值的类型为object,并且我需要在使用时强制转换它们。

JSON 输出字符串为{"Car":68.107,"Truck":48.451,"Van":798300}

字典如何知道值的类型,为什么我得到的是实际类型而不是基本类型object

【问题讨论】:

  • 您混淆了运行时类型和编译时类型。你确实需要投射。
  • Debugger 有足够的runtime关于你所质疑的类型的信息,因此能够为你提供流畅的用户体验。真正的类型仍然是object,正如您所期望的那样。
  • NewtonSoft.Json 框架基于 JSON 模式解释值类型
  • @Nkosi 这里没有架构
  • @DavidG "value": 68.107float"value": "68.107"String

标签: c# dictionary types json.net .net-4.5


【解决方案1】:

当你打电话时

JsonConvert.SerializeObject(dict);

这需要一个对象,然后计算出类型,并相应地存储它。

因此对于字典条目中的每个项目。它首先检查类型,然后根据其类型反序列化。

如果您想在 JSON 之外使用该对象,则必须使用类似

的方式检查自己
var o = dict["Car"];

if(o is int) return (int)o; // or whatever you want to do with an int
if(o is decimal) return (decimal)o; // or whatever you want to do with an decimal

【讨论】:

  • 您的意思是根据其类型对其进行序列化。当它反序列化时,它会根据序列化的值进行猜测,因为此时它没有类型信息。
  • @wllmsaccnt 是的,当然,尽管您可以通过指定 JsonConvert.Deserialize&lt;string, double&gt;(json) 来帮助它
  • JSON.Net 将其反序列化为字符串之外的任何内容,这很奇怪。它可能会使用一些启发式方法,但这没有任何意义,只需将所有值视为字符串(JSON 是一种字符串格式),您就可以了。似乎它正在工作,因为它应该能够解析内部对象,所以它急切地这样做,并试图确定最方便的类型。
【解决方案2】:

当您在调试器中检查实例时,调试器只会向您显示该项目的 .ToString() 的输出。运行以下代码:

namespace ConsoleApplication1
{
    public class Program
    {
        private static void Main(string[] args)
        {
            var dic = new Dictionary<string, object>
            {
                { "One", "1" }, { "Two", 2 },
                { "Three", 3.0 }, { "Four", new Person() },
                { "Five", new SimplePerson() },

            };
            foreach (var thisItem in dic)
            {
                // thisItem.Value will show "1", 2, 3, "Test" 
                // and ConsoleApplication1.SimplePerson
                Console.WriteLine($"{ thisItem.Key } : { thisItem.Value }");
            }

            var obj = JsonConvert.SerializeObject(dic);
        }
    }

    public class SimplePerson
    {

    }
    public class Person
    {
        public override string ToString()
        {
            return "Test";
        }
    }
}

当您将鼠标悬停在this.Value 上时,它将显示ToString() 的结果。所以它会显示以下内容:

"1"
2
3
"Test" // since Person class overrides the ToString()
// since by default when ToString() is called it will print out the object.
ConsoleApplication1.SimplePerson 

序列化

对于序列化,它将产生以下内容:

{
    "One": "1",
    "Two": 2,
    "Three": 3.0,
    "Four": {

    },
    "Five": {

    }
}

它们都被装箱为object 类型,但是当底层类型是任何类型时。所以在我们的例子中String",Int,Double,PersonandSimplePerson`。因此,在序列化过程中,它是拆箱的。

【讨论】:

    猜你喜欢
    • 2019-10-26
    • 2012-05-13
    • 2014-10-22
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多