您可以在 .NET 中从 JSON 实例化对象实例吗?
Posted
技术标签:
【中文标题】您可以在 .NET 中从 JSON 实例化对象实例吗?【英文标题】:Can you Instantiate an Object Instance from JSON in .NET? 【发布时间】:2010-09-17 00:22:50 【问题描述】:由于对象初始化器与 JSON 非常相似,现在 .NET 中有匿名类型。能够获取一个字符串(例如 JSON)并创建一个表示 JSON 字符串的匿名对象会很酷。
使用对象初始化器创建匿名类型:
var person = new
FirstName = "Chris",
LastName = "Johnson"
;
如果您可以传入对象初始化器代码的字符串表示形式(最好是 JSON 之类的)来创建具有该数据的匿名类型的实例,那就太棒了。
不知道有没有可能,因为C#不是动态的,编译器实际上是把Object Initializer转换成d Anonymous Type into strongly typed code that can run. This is explained in这篇文章的。
也许采用 JSON 并使用它创建键/值字典的功能效果最好。
我知道您可以在 .NET 中将对象序列化/反序列化为 JSON,但我正在寻找一种创建本质上松散类型的对象的方法,类似于 javascript 的工作原理。
有人知道在 .NET 中执行此操作的最佳解决方案吗?
更新:太澄清了我为什么要问这个的上下文......我在想 C# 如何在语言级别(可能)更好地支持 JSON,我正在尝试考虑今天可以完成的方法,出于概念上的原因。所以,我想我会把它贴在这里开始讨论。
【问题讨论】:
【参考方案1】:.NET 的某些语言具有鸭子类型,但使用 Dot.Notation 的 C# 是不可能的,因为 C# 要求在编译时解析所有成员引用。如果您想使用 Dot.Notation,您仍然必须在某个地方定义一个具有所需属性的类,并使用您想要从 JSON 数据实例化该类的任何方法。预定义一个类确实具有强类型、IDE 支持(包括智能感知)以及不必担心拼写错误等好处。你仍然可以使用匿名类型:
T deserialize<T>(string jsonStr, T obj) /* ... */
var jsonString = "FirstName='Chris', LastName='Johnson, Other='unused'";
var person = deserialize(jsonString, new FirstName="",LastName="");
var x = person.FirstName; //strongly-typed
【讨论】:
+1,很脏,但目前是执行 OP 想要的唯一方法。 非常好,这是我没有想到的一种方式。 既然 C# 支持动态类型,您认为答案会是什么【参考方案2】:我编写了一个相对较短的方法,它将解析 JSON 并返回一个名称/值字典,该字典可以类似于 JavaScript 中的实际对象进行访问。
以下是以下方法的示例用法:
var obj = ParseJsonToDictionary("FirstName: \"Chris\", \"Address\":Street:\"My Street\",Number:123");
// Access the Address.Number value
object streetNumber = ((Dictionary<string, object>)obj["Address"])["Number"];
还有,ParseJsonToDictionary 方法的代码如下:
public static Dictionary<string, object> ParseJsonToDictionary(string json)
var d = new Dictionary<string, object>();
if (json.StartsWith(""))
json = json.Remove(0, 1);
if (json.EndsWith(""))
json = json.Substring(0, json.Length - 1);
json.Trim();
// Parse out Object Properties from JSON
while (json.Length > 0)
var beginProp = json.Substring(0, json.IndexOf(':'));
json = json.Substring(beginProp.Length);
var indexOfComma = json.IndexOf(',');
string endProp;
if (indexOfComma > -1)
endProp = json.Substring(0, indexOfComma);
json = json.Substring(endProp.Length);
else
endProp = json;
json = string.Empty;
var curlyIndex = endProp.IndexOf('');
if (curlyIndex > -1)
var curlyCount = 1;
while (endProp.Substring(curlyIndex + 1).IndexOf("") > -1)
curlyCount++;
curlyIndex = endProp.Substring(curlyIndex + 1).IndexOf("");
while (curlyCount > 0)
endProp += json.Substring(0, json.IndexOf('') + 1);
json = json.Remove(0, json.IndexOf('') + 1);
curlyCount--;
json = json.Trim();
if (json.StartsWith(","))
json = json.Remove(0, 1);
json.Trim();
// Individual Property (Name/Value Pair) Is Isolated
var s = (beginProp + endProp).Trim();
// Now parse the name/value pair out and put into Dictionary
var name = s.Substring(0, s.IndexOf(":")).Trim();
var value = s.Substring(name.Length + 1).Trim();
if (name.StartsWith("\"") && name.EndsWith("\""))
name = name.Substring(1, name.Length - 2);
double valueNumberCheck;
if (value.StartsWith("\"") && value.StartsWith("\""))
// String Value
d.Add(name, value.Substring(1, value.Length - 2));
else if (value.StartsWith("") && value.EndsWith(""))
// JSON Value
d.Add(name, ParseJsonToDictionary(value));
else if (double.TryParse(value, out valueNumberCheck))
// Numeric Value
d.Add(name, valueNumberCheck);
else
d.Add(name, value);
return d;
我知道这个方法可能有点粗糙,可能还可以优化很多,但它是初稿,它只是工作。
另外,在你抱怨没有使用正则表达式之前,请记住,并不是每个人都真正理解正则表达式,如果需要,以这种方式编写它会使其他人更难修复。另外,我目前对正则表达式不太了解,字符串解析比较简单。
【讨论】:
【参考方案3】:您不能从方法中返回匿名类型**,因此“重新水化”匿名类型的存在将仅限于重新水化它的方法。有点无意义。
** 你可以将它作为一个对象返回(这需要反射来访问它的属性--yeech),或者你可以“通过示例进行转换”,这也是没有意义的,因为它需要额外的步骤,这意味着你已经知道对象的类型应该是什么样子,那么为什么不首先创建一个对象并填充它呢?
【讨论】:
【参考方案4】:您应该查看 JSON.net 项目:
http://james.newtonking.com/pages/json-net.aspx
您基本上是在谈论从 JSON 中水合对象的能力,这将做到。它不会做匿名类型,但也许它会让你足够接近。
【讨论】:
【参考方案5】:这是什么应用?
出于几个原因,我不会走这条路。
首先;它可能需要大量使用反射的支持代码来创建您正在谈论的透明方法。
其次,正如您所说,C# 是一种强类型语言,出于某种原因,语言规范中未包含此类内容。
第三,这样做的开销是不值得的。请记住,网页(尤其是 AJAX 查询)应该非常快,否则就达不到目的。如果你继续花 50% 的时间在 C# 和 Javascript 之间序列化你的对象,那么你就有问题了。
我的解决方案是创建一个仅封装字典并将 JSON 字符串作为 ctor 参数的类。然后只需为您要处理的每种类型的 JSON 查询扩展该类。这将是一个强类型和更快的解决方案,但仍保持可扩展性和易用性。缺点是每种类型的 JSON 请求需要编写更多代码。
:)
【讨论】:
以上是关于您可以在 .NET 中从 JSON 实例化对象实例吗?的主要内容,如果未能解决你的问题,请参考以下文章
C# 对象实例化 用json保存 泛型类 可以很方便的保存程序设置
将属性名称更改为在使用Json.net进行序列化时已实例化的派生类名称
C#代码中从SQL中查询到的DataTable传到一个javascript 函数中,请问怎么实现,最好有实例,非常感谢!!!