您可以在 .NET 中从 JSON 实例化对象实例吗?

发布于 2024-07-07 01:27:03 字数 737 浏览 12 评论 0原文

由于对象初始值设定项与 JSON 非常相似,因此现在 .NET 中出现了匿名类型。 如果能够获取字符串(例如 JSON)并创建表示 JSON 字符串的匿名对象,那就太酷了。

使用对象初始化器创建匿名类型:

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

如果您可以传入对象初始化器代码的字符串表示形式(最好是 JSON 之类的东西)来使用该数据创建匿名类型的实例,那就太棒了。

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

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

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

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

更新:太澄清了我问这个问题的背景...我正在考虑 C# 如何在语言级别(可能)更好地支持 JSON,并且我正在尝试考虑今天可以完成的方法,用于概念性的原因。 所以,我想我应该将其发布在这里以开始讨论。

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.

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.

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 in this article.

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

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.

Does anyone know the best solution for doing this in .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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

疏忽 2024-07-14 01:27:03

.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

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 does have benefits like strong typing, IDE support including intellisense, and not worrying about spelling mistakes. You can still use anonymous types:

 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
难忘№最初的完美 2024-07-14 01:27:03

您应该查看 JSON.net 项目:

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

您基本上谈论的是从 JSON 水合对象的能力,这将做到这一点。 它不会做匿名类型,但也许它会让你足够接近。

You should check out the JSON.net project:

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.

审判长 2024-07-14 01:27:03

我编写了一个相对较短的方法,它将解析 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;
}

我知道这个方法可能有点粗糙,而且可能还可以优化很多,但它是初稿,而且可以正常工作。

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

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.

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:

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.

瑾兮 2024-07-14 01:27:03

这有什么应用?

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

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

  • 出于某种原因而被排除在语言规范之外。
  • 第三,这样做的开销是不值得的。 请记住,网页(尤其是 AJAX 查询)应该非常快,否则就达不到目的。 如果您继续花费 50% 在 C# 和 Javascript 之间序列化对象,那么您就会遇到问题。

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

:)

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.

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.

:)

悲欢浪云 2024-07-14 01:27:03

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

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

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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文