在JSON中包含数据作为键名是否正确?

时间:2019-01-23 23:33:18

标签: c# json json.net standards

我正在使用提供JSON有效负载的API。 JSON中的一种特质实际上是一个数据元素,因此我无法在不添加其他类的情况下反序列化有效负载。

这是JSON:

{
      "company": "ABC Inc.",
      "packages": {
          "$package1": {
          "code": "$package1",
          "name": "Foo",
          "price": 1000
        },
        "$package2": {
          "code": "$package2",
          "name": "Bar",
          "price": 2000
        },
        "$package3": {
          "code": "$package3",
          "name": "Another",
          "price": 3000
        }
    }
}

我可以使用带有以下类的Newtonsoft.Json进行序列化:

public class Rootobject
{
    public string company { get; set; }
    public Packages packages { get; set; }
}

public class Packages
{
    public Package1 package1 { get; set; }
    public Package2 package2 { get; set; }
    public Package3 package3 { get; set; }
}

public class Package1
{
    public string code { get; set; }
    public string name { get; set; }
    public int price { get; set; }
}

public class Package2
{
    public string code { get; set; }
    public string name { get; set; }
    public int price { get; set; }
}

public class Package3
{
    public string code { get; set; }
    public string name { get; set; }
    public int price { get; set; }
} 

使用这种方法,我可以使用Newtonsoft.Json反序列化,但是如果以后添加了“ package4”,则需要我进行代码更改。

我应该推迟开发该API并坚持使用一系列软件包,而不是当前的实现方式吗?

2 个答案:

答案 0 :(得分:7)

您可以使用Dictionary<>进行此操作,例如:

public partial class Rootobject
{
    public string Company { get; set; }
    public Dictionary<string, Package> Packages { get; set; }
}

public partial class Package
{
    public string Code { get; set; }
    public string Name { get; set; }
    public long Price { get; set; }
}

反序列化是这样的:

var result = JsonConvert.DeserializeObject<Rootobject>(json);

并像这样使用它:

foreach (var element in result.Packages)
{
    Console.WriteLine($"Package: {element.Key} has name {element.Value.Name}");
}

哪个会输出:

Package: $package1 has name Foo
Package: $package2 has name Bar
Package: $package3 has name Another

答案 1 :(得分:-1)

具有此类重复的类将大大降低代码的可重用性。最好使用软件包列表来实现:

public class Rootobject
{
    public string company { get; set; }
    public List<Package> packages { get; set; }
}

您的Package类:

public class Package
{
    public string code { get; set; }
    public string name { get; set; }
    public int price { get; set; }
} 

这将允许一个公司拥有多个Package对象。唯一的缺点是,您还必须要求将其也更改为数组,但是要考虑最好的做法,因为似乎不需要包装号。理想情况下,您将以以下方式接收JSON有效负载:

{
      "company": "ABC Inc.",
      "packages": [
        {
          "name": "Foo",
          "price": 1000
        },
        {
          "name": "Bar",
          "price": 2000
        },
        {
          "name": "Another",
          "price": 3000
        }
    ]
}

如果name不是唯一的,也可能会获得一个ID。