反序列化 MandrillApp Webhook 响应

3

MandrillApp API据说会发送一个MIME类型为application/x-www-form-urlencoded的JSON编码消息数组

我遇到的问题是收到的数据看起来像这样:

mandrill_events=%5B%7B%22event%22%3A%22send%22
%2C%22msg%22%3A%7B%22ts%22%3A136510999...etc

它经过URL解码后是:

mandrill_events=[{"event":"send","msg":{
"ts":1365109999,"subject"...etc

我尝试将此字符串反序列化为表示JSON数据的类,但JSON.NET反序列化程序报错。

代码

m = JsonConvert.DeserializeObject<MandrillEvents>(s);

异常

解析值时遇到意外字符:m。路径',第0行,第0个位置。

根据我的理解,字符串中的mandrill_events=部分是无效的。

  • 这个字符串应该能够被反序列化吗?
  • 在反序列化时,是否有我遗漏的选项?
  • 我该如何处理这个问题?
1个回答

8
"mandrill_events=" 不是有效的 JSON 格式。如果你把它移除,就可以解析了。"
string validJson = originalText.Replace("mandrill_events=", ""); 
var m = JsonConvert.DeserializeObject<MandrillEvents[]>(validJson);

如果这样不行,我们需要查看更多的文本以确定什么其他内容不是有效的JSON。JSON非常棒,因为它只有几种简单的数据类型:对象、数组、布尔值、字符串、整数等等。请参见此处以获取所有有效类型:http://json.org/
正如Brian Rogers所提到的,您还将反序列化为错误的类型(您有一个对象数组,而不是单个对象)。
如果您想检查整个JSON字符串是否有效,可以使用以下方法:
JArray array = JArray.Parse(validJson);

如果你有任何疑问,可以使用:
JToken token = JToken.Parse(validJson);

这段文本讨论了JSON格式的使用。它可以适用于对象、数组和值,虽然在反序列化时建立数据模型更好,因为这样可以获得强类型,但是至少可以确保你有有效的JSON数据之后再尝试构建数据模型。文中还提到了Visual Studio 2012的一个非常酷的功能,即在编辑中点击“粘贴为JSON类”,将有效的JSON文本复制到剪贴板中,并将其粘贴为有效的C#类,从而使从复杂的JSON构建POCO模型变得更容易且不容易出错。接下来文章回答了一个问题,“他们为什么要以这种方式发送响应?”作者认为这很奇怪,需要客户端去解析/读取响应,而几乎任何数据都可以通过JSON表示,这也是为什么它成为Web API的数据交换格式的一种流行选择。当您想要发送自定义数据格式时,可能需要客户端编写自己的解析器甚至使用正则表达式,这就是重新发明轮子了。在这种情况下,他们将一个格式嵌入到另一个格式中,这仍然相当丑陋,并且阻止您使用单个解析器。最后,作者猜测这可能是为了向后兼容性,因为他们最初将API公开为application/x-www-form-urlencoded,并且不想破坏现有的客户端,因此继续使用它但是嵌入JSON对象。

谢谢。他们为什么会在字符串中包含那个? - Ablue
你需要反序列化为 List<MandrillEvent>,因为 JSON 是一个数组,而不是单个对象。 - Brian Rogers
@BrianRogers:是的,我明白了。在尝试反序列化时,我创建了MandrillEvent,它具有属性mandrill_events,这是一个WebHookEvent数组。但从外观上看,那真的不是问题所在。 - Ablue
@Despertar:我可以包含完整的字符串,但其余部分似乎是有效的。 - Ablue
“paste as JSON” 类听起来很不错。您能否评论一下为什么他们会以这种方式发送响应? - Ablue
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接