我正在编写rest api,并且对json序列化还很陌生。
我知道json对象由成对的<key>:<value>
组成。
我有一个对象“ channels”,其中包含多个通道对象,这些对象包含一个id和其他一些属性,例如“ x”,“ y”和“ z”。
在我们的团队中,我们发现了两种表示对象“通道”的方法,我看到人们实现的通常方法是这样的:
{
"channels":
[
{
"id":0,
"x":0,
"y":0,
"z":0
},
...
]
}
还有这个版本,使用id作为密钥:
{
"channels":
{
"0":
{
"x":0,
"y":0,
"z":0
},
...
}
}
请注意,第一种实现显式使用数组,而第二种依赖<key>
直接访问特定通道。
代表此对象的最佳方法是什么?可以将键表示为值(例如前一种情况的ID)吗?
目前只有两个频道(标识分别为0和1),但将来我们可能会添加更多频道。
答案 0 :(得分:1)
您应该始终偏爱第一种方法,因为以这种方式使用JSON更容易,更直观。如果有人想使用您的API,他们可能会创建要反序列化的模型类。使用第一种方法,这很容易:
public class RootObject
{
public List<Channel> channels { get; set; }
}
public class Channel
{
public int id { get; set; }
public int x { get; set; }
public int y { get; set; }
public int z { get; set; }
}
实际上,您可以仅使用JSON并将其转储到http://json2csharp.com/之类的生成器工具中以获取这些类(这就是我在这里所做的)。
相反,在第二种方法中,JSON中代表ID的键是动态的,生成器不会识别出这些键。因此,您将获得类似这样的内容,需要手动对其进行纠正:
public class RootObject
{
public Channels channels { get; set; }
}
public class Channels
{
public __invalid_type__0 __invalid_name__0 { get; set; }
}
public class __invalid_type__0
{
public int x { get; set; }
public int y { get; set; }
public int z { get; set; }
}
我已经看到有人尝试像这样修复它,这将适用于您的单渠道示例,但显然无法扩展:
public class RootObject
{
public Channels channels { get; set; }
}
public class Channels
{
[JsonProperty("0")]
public Data Item0 { get; set; }
}
public class Data
{
public int x { get; set; }
public int y { get; set; }
public int z { get; set; }
}
要使用动态键正确使用JSON,这些类实际上需要如下所示:
public class RootObject
{
public Dictionary<string, Channel> channels { get; set; }
}
public class Channel
{
public int x { get; set; }
public int y { get; set; }
public int z { get; set; }
}
但是,对于临时用户而言,您需要在此处使用字典这一事实并不总是很直观。实际上,我已经忘记了“我如何处理JSON中的动态键”这个问题的味道了。在StackOverflow上为asked。为您的用户帮个忙,而不必让他们思考。
除了反序列化JSON之外,第一个模型也是优越的,因为Channel
对象包含 all 有关通道的数据:id
位于对象内部本身。这样很容易传递和使用。如果需要进行键查找,稍后将List<Channel>
转换为Dictionary<int, Channel>
也很简单:
var dict = rootObject.channels.ToDictionary(ch => ch.id);
使用第二种方法时,id
与其余通道数据是分开的,因此,如果要将通道传递给需要两者的方法,则必须传递两个参数或创建一个新参数模型类将所有内容包装在一起。换句话说,使用起来比较尴尬。
最重要的是,我认为使用第二种方法完全没有真正的好处。先去吧。
答案 1 :(得分:0)
如果通道是对象而不是数组,则在定义通道特定合同时应使用第一个选项。如果某个频道可以包含频道的子集,那么我建议您使用第二种方法,因为您可以通过使用密钥(该密钥必须唯一才能正常工作)来访问特定的子集。