Json:如何使用json.net正确剥离转义字符

Sha*_*nce 12 c# string json json.net

我有以下格式的json响应.

"[{\\\"JobID\\\":\\\"1\\\",\\\"BillGenerationDate\\\":\\\"4/29/2013 2:53:34 PM\\\",\\\"BillID\\\":\\\"115743\\\",\\\"BillNo\\\":\\\"115743\\\",\\\"CustomerID\\\":\\\"4041705\\\",\\\"PayStatus\\\":\\\"0\\\",\\\"PaymentRequiredStatus\\\":\\\"True\\\",\\\"ProductName\\\":\\\"Epic FBO test\\\",\\\"Description\\\":\\\"Epic Automation 2\\\\r\\\\n\\\",\\\"ProductType\\\":\\\"eBill \\\",\\\"DueType\\\":\\\"-1\\\",\\\"DueDate\\\":\\\"2013-03-15\\\",\\\"Amount\\\":\\\"63.70\\\",\\\"Cost\\\":\\\"\\\"},
{\\\"JobID\\\":\\\"9\\\",\\\"BillGenerationDate\\\":\\\"5/2/2013 10:21:39 AM\\\",\\\"BillID\\\":\\\"115743\\\",\\\"BillNo\\\":\\\"115743\\\",\\\"CustomerID\\\":\\\"4041705\\\",\\\"PayStatus\\\":\\\"0\\\",\\\"PaymentRequiredStatus\\\":\\\"True\\\",\\\"ProductName\\\":\\\"FBO Test Product\\\",\\\"Description\\\":\\\"FBO Product Test\\\",\\\"ProductType\\\":\\\"eBill \\\",\\\"DueType\\\":\\\"-1\\\",\\\"DueDate\\\":\\\"2013-05-01\\\",\\\"Amount\\\":\\\"150.70\\\",\\\"Cost\\\":\\\"\\\"}]
Run Code Online (Sandbox Code Playgroud)

我相信json.net处理转义字符,我使用下面的代码将其反序列化为字典集合.

var billList = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(contentCorrected);
Run Code Online (Sandbox Code Playgroud)

但是这个json解析会抛出异常"无效的属性标识符:.Path'[0]',第1行,第2位." 我们可以通过操纵json响应字符串来解决这个问题吗?

Bij*_*ose 16

string contentCorrected = contentCorrected.Replace(@"\", "");在反序列化过程之前尝试.

  • 这可能会导致无效的 json (3认同)
  • 如今,我发现这个答案有点“快速而肮脏”。如果您仍在使用 Newtonsoft 进行序列化,我会选择 @Johan Alzate 答案 (2认同)

Joh*_*ate 5

简短的回答:首先,您需要对转义的字符串进行反序列化,而不是对目标CLR类型进行反序列化,而对其他字符串进行反序列化:

// Initial example json string:  "\"{\\\"Property1\\\":1988,\\\"Property2\\\":\\\"Some data :D\\\"}\""


// First, deserialize to another string (unescaped string).
string unescapedJsonString = JsonConvert.DeserializeObject<string>(escapedJsonString);
Debug.WriteLine(unescapedJsonString);
// Prints:
// "{\"Property1\":1988,\"Property2\":\"Some data :D\"}"


// Second, deserialize to another string, again (in this case is necessary)
var finalUnescapedJsonString = JsonConvert.DeserializeObject<string>(unescapedJsonString);
Debug.WriteLine(finalUnescapedJsonString);
// This time prints a final, unescaped, json string:
// {"Property1":1988,"Property2":"Some data :D"}


// Finally, perform final deserialization to the target type, using the last unescaped string.
MyClass targetObject = JsonConvert.DeserializeObject<MyClass>(finalUnescapedJsonString);
Run Code Online (Sandbox Code Playgroud)

长答案(但很有趣) 使用string.Replace(...可能会生成无效的字符串,因为它可能损坏需要反斜杠正确反序列化的某些特殊字符。

通常,当已经是json字符串的字符串再次序列化(甚至更多次)时,会生成这种转义的字符串。这会导致类似“各种级别的序列化”(实际上是带有保留字符的字符串的序列化),结果是反斜杠字符(或一组一个,两个或多个反斜杠:\,\\,\\\ )散布在整个字符串中。因此,正确删除它们不足以用空值替换它们。

正确的方法获取未转义的字符串的更好方法是对字符串类型进行第一个反序列化(如有必要,重复几次),然后对目标CLR类型进行最后的反序列化:

// -- SERIALIZATION --

// Initial object
MyClass originObj = new MyClass { Property1 = 1988, Property2 = "Some data :D" };

// "First level" Of serialization.
string jsonString = JsonConvert.SerializeObject(originObj);
Debug.WriteLine(jsonString);
// Prints: 
// {"Property1":1988,"Property2":"Some data :D"}


// "Second level" of serialization.
string escapedJsonString = JsonConvert.SerializeObject(jsonString);
Debug.WriteLine(escapedJsonString);            
// "{\"Property1\":1988,\"Property2\":\"Some data :D\"}"
// Note the initial and final " character and de backslash characters

// ...
// at this point you could do more serializations ("More levels"), Obtaining as a result more and more backslash followed,
// something like this:
// "\"{\\\"Property1\\\":1988,\\\"Property2\\\":\\\"Some data :D\\\"}\""
// Note that is... very very crazy :D
// ...

// -- DESERIALIZATION --

// First deserialize to another string (unescaped string).
string unescapedJsonString = JsonConvert.DeserializeObject<string>(escapedJsonString);
Debug.WriteLine(unescapedJsonString);
// Prints:
// {"Property1":1988,"Property2":"Some data :D"}

// ...
// at this point you could repeat more deserializations to string, if necessary. For example if you have many backslash \\\
// ...

// Finally, perform final deserialization to the target type, using the last unescaped string.
MyClass targetObject = JsonConvert.DeserializeObject<MyClass>(unescapedJsonString);
Run Code Online (Sandbox Code Playgroud)