我正在编写一个rest api,我对json序列化很陌生。
我知道一个 json 对象由成对的 <key>:<value>.
我有一个对象“channels”,它包含多个通道对象,这些对象包含一个 id 和一些其他属性,如“x”、“y”和“z”。
在我们的团队中,我们发现了两种表示对象“通道”的方式,我看到人们实现的通常方式是这样的:
{
"channels":
[
{
"id":0,
"x":0,
"y":0,
"z":0
},
...
]
}
Run Code Online (Sandbox Code Playgroud)
还有这个版本,它使用 id 作为键:
{
"channels":
{
"0":
{
"x":0,
"y":0,
"z":0
},
...
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,第一个实现显式使用数组,而第二个实现依赖于<key>直接访问特定通道。
表示这个对象的最佳方式是什么?可以将键表示为值(如前一种情况的 id)吗?
现在只有两个通道(总是 id 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; }
}
Run Code Online (Sandbox Code Playgroud)
实际上,您可以直接获取 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; }
}
Run Code Online (Sandbox Code Playgroud)
我见过一些人尝试像这样修复它,这将适用于您的单通道示例,但显然不会扩展:
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; }
}
Run Code Online (Sandbox Code Playgroud)
要使用动态键正确使用 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; }
}
Run Code Online (Sandbox Code Playgroud)
然而,您需要在此处使用字典这一事实对于临时用户而言并不总是直观的。事实上,我已经忘记了“我如何处理 JSON 中的动态键?”这个问题的次数。在 StackOverflow上被问到。帮您的用户一个忙,不要让他们考虑。
除了反序列化 JSON 之外,第一个模型也更优越,因为该Channel对象包含有关通道的所有数据:idis 在对象本身内部。以这种方式传递和使用很容易。如果您需要进行密钥查找,将 a 转换List<Channel>为 a也很简单Dictionary<int, Channel>:
var dict = rootObject.channels.ToDictionary(ch => ch.id);
Run Code Online (Sandbox Code Playgroud)
使用第二种方法,id它与通道数据的其余部分是分开的,所以如果你想将通道传递给一个需要两者的方法,你要么必须传递两个参数,要么创建一个新的模型类来将所有内容包装在一起。换句话说,使用起来更别扭。
最重要的是,我认为使用第二种方法根本没有真正的好处。跟着第一个走。
| 归档时间: |
|
| 查看次数: |
773 次 |
| 最近记录: |