有没有一种方法可以根据使用情况内联定义类?

时间:2019-04-11 19:43:26

标签: c# json

我正在编写一项服务,以便通过公司中的另一个团队通过HTTP从API检索数据。来自其API的JSON响应主体看起来像这样:

"SomeObject": {
    "SomeInnerObject": {
        "SomeProperty": {
            "Id": "123",
            "Type": "abc",
            "Name": "some value"
        }
    }
}

我正在编写一个C#类以将数据存储在内存中,以便进行一些比较。 JSON对象的嵌套使该类看起来令人讨厌地重复:

public class MyClass 
{
    public SomeObjectModel SomeObject { get; set; }
    public class SomeObjectModel
    {
        public SomeInnerObjectModel InnerObject { get; set; }
        public class SomeInnerObjectModel
        {
            // etc...
        }
    }
}

我肯定知道诸如“ SomeObjectModel”之类的内部类只能从其他地方读取而不会在其他地方实例化,所以有没有办法将类定义和属性定义行组合成更类似的东西? / p>

public class MyClass
{
    public SomeObject { get; set; } :
    {
        public SomeInnerObject { get; set; } :
        {
            // etc...
        }
    }
}

编辑:

JSON中将包含数组,因此,如果您提议使用泛型等替代方案,请考虑到这一点。

4 个答案:

答案 0 :(得分:6)

如果仅使用此方法反序列化JSON,则甚至无需定义类。可以使用嵌套的anonymous type

首先,创建并填充(具有虚拟值)具有您需要能够读取的属性的匿名类型。然后将其作为第二个参数传递给DeserializeAnonymousType<T>(string,T)

结果是您创建的具有相同匿名类型的新实例,但是现在它填充了JSON中的值。

var json = @"{'SomeObject': {'SomeInnerObject': {'SomeProperty': {'Id': '123','Type': 'abc','Name': 'some value'}}}}";

var template = new
{
    SomeObject = new
    {
        SomeInnerObject = new 
        { 
            SomeProperty = new 
            {
               Id = default(int),
               Type = default(string),
               Name = default(string)
            }
        }
    }
};

var result = JsonConvert.DeserializeAnonymousType(json, template);
var id = result.SomeObject.SomeInnerObject.SomeProperty.Id;
var type = result.SomeObject.SomeInnerObject.SomeProperty.Type;
var name = result.SomeObject.SomeInnerObject.SomeProperty.Name;

Console.WriteLine("{0} {1} {2}", id, type, name);

输出:

123 abc some value

请参阅我的working example on DotNetFiddle

编辑:如果JSON包含一个数组,则可以使用new[] {}根据类型推断创建一个数组,然后将匿名类型放入其中,如下所示:

var json = @"{ 'SomeObjects': [ { 'Id': '123', 'Name': 'some value' }, { 'Id': '456', 'Name': 'another value' } ]}";

var template = new
{
    SomeObjects = new [] { new { Id=default(int), Name=default(string)} }
};

答案 1 :(得分:2)

简短的回答是“否”,C#不支持该语法糖的任何版本。 C#中最接近的东西可能是匿名类型或值元组。

其他语言具有相似的功能:

  • C ++在声明中支持“内联类”。
  • Java支持比C#匿名记录类型更复杂的匿名类。
  • Scala支持案例类,这些案例类在声明的标题中声明其成员。

以此类推。我认为第一件事是最接近您要寻找的东西。

在过去的十年中,针对C#多次提出了标量样式的类声明,并且最终可能将其纳入C#8中。参见https://blog.cdemi.io/whats-coming-in-c-8-0-records/

答案 2 :(得分:0)

您可以使用dynamic type。这是一个最小的示例:

using Newtonsoft.Json;
using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic x = JsonConvert.DeserializeObject("[{key: '1001', value: 'test'}, {key: '1002', value: 'test2'}, ]");
            Console.WriteLine(x[0].key);
            Console.WriteLine(x[0].value);
            Console.WriteLine(x[1].key);
            Console.WriteLine(x[1].value);
            Console.ReadLine();
        }
    }
}

答案 3 :(得分:0)