C# 你能在 .NET 中从 JSON 实例化一个对象实例吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/199718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:43:33  来源:igfitidea点击:

Can you Instantiate an Object Instance from JSON in .NET?

c#javascriptjsonanonymous-typesobject-initializers

提问by Chris Pietschmann

Since Object Initializers are very similar to JSON, and now there are Anonymous Types in .NET. It would be cool to be able to take a string, such as JSON, and create an Anonymous Object that represents the JSON string.

由于对象初始值设定项与 JSON 非常相似,现在 .NET 中有匿名类型。能够接受一个字符串(例如 JSON)并创建一个表示 JSON 字符串的匿名对象会很酷。

Use Object Initializers to create an Anonymous Type:

使用对象初始值设定项创建匿名类型:

var person = new {
    FirstName = "Chris",
    LastName = "Johnson"
};

It would be awesome if you could pass in a string representation of the Object Initializer code (preferably something like JSON) to create an instance of an Anonymous Type with that data.

如果您可以传入对象初始值设定项代码的字符串表示(最好是类似 JSON 的内容)以使用该数据创建匿名类型的实例,那就太棒了。

I don't know if it's possible, since C# isn't dynamic, and the compiler actually converts the Object Initializer and Anonymous Type into strongly typed code that can run. This is explained inthis article.

我不知道这是否可能,因为 C# 不是动态的,而且编译器实际上将对象初始值设定项和匿名类型转换为可以运行的强类型代码。这在本文中进行了解释

Maybe functionality to take JSON and create a key/value Dictionary with it would work best.

也许采用 JSON 并使用它创建键/值字典的功能最有效。

I know you can serialize/deserializer an object to JSON in .NET, but what I'm look for is a way to create an object that is essentially loosely typed, similarly to how JavaScript works.

我知道您可以在 .NET 中将对象序列化/反序列化为 JSON,但我要寻找的是一种创建基本上松散类型的对象的方法,类似于 JavaScript 的工作方式。

Does anyone know the best solution for doing this in .NET?

有谁知道在 .NET 中执行此操作的最佳解决方案?

UPDATE: Too clarify the context of why I'm asking this... I was thinking of how C# could better support JSON at the language level (possibly) and I was trying to think of ways that it could be done today, for conceptual reasons. So, I thought I'd post it here to start a discussion.

更新:太澄清了为什么我问这个的上下文......我在考虑 C# 如何在语言级别(可能)更好地支持 JSON,并且我试图考虑今天可以完成的方法,用于概念原因。所以,我想我会在这里发布它来开始讨论。

采纳答案by Mark Cidade

There are languages for .NET that have duck-typing but it's not possible with C# using Dot.Notation since C# requires that all member references are resolved at compile time. If you want to use the Dot.Notation, you still have to define a class somewhere with the required properties, and use whatever method you want to instantiate the class from the JSON data. Pre-defining a class doeshave benefits like strong typing, IDE support including intellisense, and not worrying about spelling mistakes. You can still use anonymous types:

有些 .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

回答by Chris Pietschmann

What is the application for this?

这有什么应用?

I would not go down this road for a few reasons.

由于一些原因,我不会走这条路。

  • First; it may require a lot of support code using reflection and such to create the transparent method that you are talking about.

  • Second, like you said, C# is a strongly typed language and things like these were left out of the language specification for a reason.

  • Third, the overhead for doing this would not be worth it. Remember that web pages (especially AJAX queries) should be really fast or it defeats the purpose. If you go ahead and spend 50% serializing your objects between C# and Javascript then you have a problem.

  • 第一的; 它可能需要使用反射等大量支持代码来创建您正在谈论的透明方法。

  • 其次,就像你说的,C# 是一种强类型语言,出于某种原因,这些东西被排除在语言规范之外。

  • 第三,这样做的开销是不值得的。请记住,网页(尤其是 AJAX 查询)应该非常快,否则就会失去目的。如果你继续花费 50% 的时间在 C# 和 Javascript 之间序列化你的对象,那么你就有问题了。

My solution would be to create a class that just encapsulates a dictionary and that takes a JSON string as a ctor argument. Then just extend that class for each type of JSON query you want to handle. This will be a strongly typed and faster solution but still maintain extensibility and ease of use. The downside is that there is more code to write per type of JSON request.

我的解决方案是创建一个只封装字典的类,并将 JSON 字符串作为 ctor 参数。然后只需为您要处理的每种类型的 JSON 查询扩展该类。这将是一个强类型和更快的解决方案,但仍保持可扩展性和易用性。缺点是每种类型的 JSON 请求需要编写更多代码。

:)

:)

回答by Jason Hymanson

You should check out the JSON.netproject:

您应该查看JSON.net项目:

http://james.newtonking.com/pages/json-net.aspx

http://james.newtonking.com/pages/json-net.aspx

You are basically talking about the ability to hydrate an object from JSON, which this will do. It won't do the anonymous types, but maybe it will get you close enough.

您基本上是在谈论从 JSON 中提取对象的能力,这可以做到。它不会做匿名类型,但也许它会让你足够接近。

回答by Jason Hymanson

You can't return an anonymous type from a method**, so a "rehydrated" anonymous type's existence would be limited to the method in which it is rehydrated. Kind of pointless.

您不能从方法** 返回匿名类型,因此“重新水化”匿名类型的存在将仅限于重新水化它的方法。有点无意义。

** You can return it as an object (which requires reflection to access its properties--yeech) or you can "cast it by example", which is pointless as well, since it takes extra steps and it means you already KNOW what the object's type should look like, so why not just create an object and fill it up in the first place?

** 你可以将它作为一个对象返回(这需要反射来访问它的属性——yeech)或者你可以“通过例子来投射它”,这也是毫无意义的,因为它需要额外的步骤,这意味着你已经知道什么是对象的类型应该看起来像,那么为什么不首先创建一个对象并填充它呢?

回答by Chris Pietschmann

I wrote a relatively short method that will Parse JSON and return a name/value Dictionary that can be accessed similarly to the actual object in JavaScript.

我编写了一个相对较短的方法,它将解析 JSON 并返回一个名称/值字典,该字典可以类似于 JavaScript 中的实际对象进行访问。

Here's a sample usage of the below method:

以下是以下方法的示例用法:

var obj = ParseJsonToDictionary("{FirstName: \"Chris\", \"Address\":{Street:\"My Street\",Number:123}}");

// Access the Address.Number value
object streetNumber = ((Dictionary<string, object>)obj["Address"])["Number"];

And, here's the code for the ParseJsonToDictionary method:

而且,这是 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;
}

I know this method may be a little rough, and it could probably be optimized quite a bit, but it's the first draft and it just works.

我知道这个方法可能有点粗糙,它可能会优化很多,但它是初稿,它只是有效。

Also, before you complain about it not using regular expressions, keep in mind that not everyone really understands regular expressions, and writing it that way would make in more difficult for others to fix if needed. Also, I currently don't know regular expression too well, and string parsing was just easier.

此外,在你抱怨它没有使用正则表达式之前,请记住,并不是每个人都真正理解正则表达式,如果需要,以这种方式编写它会使其他人更难修复。另外,我目前不太了解正则表达式,字符串解析更容易。