Json: как правильно убрать escape-символы с помощью 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\\\":\\\"\\\"}]

Я считаю, что json.net обрабатывает escape-символы, и я использовал приведенный ниже код для десериализации его в коллекцию словарей.

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

Но это json parsing исключает исключение "Недопустимый символ идентификатора свойства:. Path '[0]', строка 1, позиция 2." Можем ли мы решить это, манипулируя строкой ответа json?

Ответ 1

Попробуйте string contentCorrected = contentCorrected.Replace(@"\", ""); перед процессом десериализации.

Ответ 2

  • Перед десериализацией удалите все символы "\". Используйте функцию замены.

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

  • Строка Json неполна или не имеет типа List<Dictionary<string, string>>". Исправьте тип, который вы хотите преобразовать json. Я немного изменил ваш json, и это сработало.

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

Ответ 3

Для меня код ниже работает

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

Ответ 4

Проблема возникает, когда в ответе используются действительные двойные кавычки. Удаление и/или замена не разрешат это во всех случаях. Это тоже расстроило меня, пока я не нашел простое решение:

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

Ответ 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);

ПОЛНЫЙ ОТВЕТ (но интересно) Использование 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);