【问题标题】:Json: how to properly strip the escape characters with json.netJson:如何使用 json.net 正确剥离转义字符
【发布时间】:2013-05-02 06:32:46
【问题描述】:

我有以下格式的 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\\\":\\\"\\\"}]

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

var billList = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(contentCorrected);

但是这个 json 解析抛出异常 “无效的属性标识符字符:。路径'[0]',第 1 行,位置 2。” 我们可以通过处理 json 响应字符串来解决这个问题吗?

【问题讨论】:

标签: c# json string json.net


【解决方案1】:

简短的回答:首先你需要反序列化转义的字符串,但不要反序列化为目标 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);

长答案(但很有趣) 使用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);

【讨论】:

  • 卡在某事上好几天了,谢谢!你完全正确!
  • 这似乎是最安全的方式。
【解决方案2】:

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

【讨论】:

  • 应该是contentCorrected = contentCorrected.Replace(@"\""", @"""")
  • contentCorrected = contentCorrected.Replace(@"\", string.Empty)
  • 这会导致json无效
  • 现在,我觉得这个答案有点“快'n'dirty”。如果您仍在使用 Newtonsoft 进行序列化,我会选择 @Johan Alzate 的答案
【解决方案3】:
  1. 在反序列化之前删除所有“\”字符。使用替换功能。

    yourJsonString.Replace("\\\\\", "");

  2. 您的 Json 字符串不完整或似乎不是 List&lt;Dictionary&lt;string, string&gt;&gt;" 类型。更正您希望转换 json 的类型。 我对您的 json 进行了如下修改,它起作用了。

    newJson = "{ \"array\":" + yourJsonString + "}"

【讨论】:

    【解决方案4】:

    在答案中使用有效的双引号时会出现问题。删除和/或更换不会在所有情况下都解决这个问题。 在我找到一个简单的解决方案之前,我也很沮丧:

    var billList = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(@contentCorrected);
    

    【讨论】:

      【解决方案5】:

      对我来说,下面的代码有效

      string contentCorrected = contentCorrected.Replace(**@"\""", ""**);
      

      【讨论】:

      • 这甚至不能编译?
      猜你喜欢
      • 2018-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-05
      相关资源
      最近更新 更多