【发布时间】:2017-02-28 20:47:07
【问题描述】:
我希望这是非常简单的事情,并且必须是其他开发人员的常见场景。
我正在从 SQL 发送一个包含错误详细信息的 OUT 变量。在我的 DataLayer API 中,我在 VS Debugger 中检查它,它就是这样显示的:
var string_from_stored_proc = "[{\"errornumber\":2627,\"errormessage\":\"Violation of UNIQUE KEY constraint 'KEY_Subject'. Cannot insert duplicate key in object 'edu.Subject'. The duplicate key value is (MATS10, 2).\",\"errorstate\":1,\"errorseverity\":14,\"errorline\":36,\"errroprocedure\":\"SPCreateSubject\",\"xactstate\":1}]"
我了解 VS 调试器将转义 () 添加到字符串中。 当我尝试使用以下方法反序列化此字符串时:
JsonConvert.DeserializeObject<my_error_object>(string_from_stored_proc);
我收到此错误:
{"无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型 'BaaS.DTO.SQLErrorHandler' 因为该类型需要 JSON 对象 (例如 {\"name\":\"value\"})正确反序列化。\r\n修复此问题 错误要么将 JSON 更改为 JSON 对象(例如 {\"name\":\"value\"}) 或将反序列化类型更改为数组或 实现集合接口的类型(例如 ICollection、IList) 比如可以从 JSON 数组反序列化的 List。 JsonArrayAttribute 也可以添加到类型中以强制它 从 JSON 数组反序列化。\r\n路径 '',第 1 行,位置 1。"}
json2csharp.com 无法转换此 JSON。如果我删除所有反斜杠,它就可以完成工作。下面是my_error_object(或由json2sharp转换的)类:
public class my_error_object
{
public int errornumber { get; set; }
public string errormessage { get; set; }
public int errorstate { get; set; }
public int errorseverity { get; set; }
public int errorline { get; set; }
public string errroprocedure { get; set; }
public int xactstate { get; set; }
}
我尝试处理 string_from_stored_proc 并删除所有反斜杠,但我无法删除转义字符(我认为这是预期的行为)。使用这些斜线,我无法反序列化字符串。
解决方法:
如果我使用 var outputJson = Newtonsoft.Json.Linq.JToken.Parse(string_from_stored_proc); ,它会给出以下输出:
{[
{
"errornumber": 2627,
"errormessage": "Violation of UNIQUE KEY constraint 'KEY_Subject'. Cannot insert duplicate key in object 'edu.Subject'. The duplicate key value is (MATS10, 2).",
"errorstate": 1,
"errorseverity": 14,
"errorline": 36,
"errroprocedure": "SPCreateSubject",
"xactstate": 1
}
]}
删除开始和结尾的大括号后,可以使用 NewtonSoft 进行反序列化。
但是,当我使用 BadRequest(deserialized_string_from_stored_proc) 从 DataLayer 发送它时
并使用
var output = await response.Content.ReadAsAsync<SQLErrorHandler>();
输出变量再次有很多额外的字符,然后我需要再次处理。对我有用的唯一方法是使用 HttpResults.OK(object) 发送反序列化对象并在我的 BusinessLayer 中读取它。我不想这样做,因为在发生错误时它不是正确的返回类型。
我做得对吗?我有两个问题:
- 有没有办法反序列化给定的字符串并使用 给BusinessLayer不用字符串处理吗?
- 如果 first 不可能,我可以简单地将字符串传递给 BusinessLayer 并在那里反序列化(首选方式)?
我很高兴提供更多信息或代码 sn-p 来重现错误。
编辑: 根据@Equalsk 的建议,我已经能够正确反序列化它。但是,它目前在数据层中。这是输出:
var equalskObj = JsonConvert.DeserializeObject<List<SQLErrorHandler>>(outputFromSP.Value.ToString());
return Ok(equalskObj);
但是,我仍然无法采用首选方式(#2)。如果我使用 return BadRequest(string_from_stored_proc) 将字符串发送到 BusinessLayer,它会发送
"{\r\n \"消息\": \"[{\\"errornumber\\":2627,\\"errormessage\\":\\"违规 唯一键约束“KEY_Subject”。无法插入重复键 对象'edu.Subject'。重复键值为 (MATS10, 2).\\",\\"errorstate\\":1,\\"errorseverity\\":14,\\"errorline\\":36,\\"errroprocedure\\":\\"SPCreateSubject\ \",\\"xactstate\\":1}]\"\r\n}"
我仍然需要处理它。有没有更干净的方式发送它然后按照建议进行转换?我想我应该为此发布一个简化的问题,因为这些是单独的问题。我真的很想看看最好的方法是什么。
【问题讨论】:
-
你试过
JsonConvert.DeserializeObject<List<my_error_object>>(string_from_stored_proc);吗? -
它正在寻找列表/数组类型,因为您的 SQL 字符串在其内容周围有
[和]。删除那些,然后反序列化。 -
@Equalsk - 非常感谢。它成功了。我不知何故忽略了它正在返回一个列表,即使在存储过程中设置的返回变量是一个 varchar(C# 模型中的字符串)。
-
但是,我仍然坚持使用 return Ok(object),而不是能够使用 BadRequest(string_from_stored_proc) 发送干净的错误字符串并在 BusinessLayer 中对其进行反序列化。我已经用输出更新了问题。再次感谢。 @MikeMcCaughan - 虽然你的答案有效,但我首先不想这样做,因为它涉及手动字符串处理。
标签: c# json json.net asp.net-web-api2 deserialization