Нужна помощь по регулярному выражению .NET для разбора строк JSON - PullRequest
2 голосов
/ 23 декабря 2010

Я пишу JSON-анализатор для .NET, и он до сих пор отлично разбирает объекты JSON. Одна проблема, с которой я сталкиваюсь, заключается в том, что она будет анализировать простые строки, но не будет анализировать сложные строки. Вот пример:

Он будет анализировать \"Hi there!\" как строку.

Не будет разбирать \"Hi !*\t\r\n,,{}]][] (.&^.)@!+=~`' there\"

Спецификация, которую я использую для строки JSON, прямо с веб-сайта JSON .

Мои строки регулярных выражений .NET (как я интерпретировал с сайта):

string json_char = @"(\\""|\\\\|\\/|\\b|\\f|\\n|\\r|\\u|[^(\""|\\)])";
string json_string = @"(\""" + json_char + @"*\"")";

Выше приведено то же, что и в Visual Studio. Обратите внимание, что с символами @ две двойные кавычки ("") требуются для указания одного символа двойной кавычки (") в фактическом строковом значении.

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

Мне нужна строка регулярного выражения, которая будет анализировать строку JSON, как указано на веб-сайте. Любая помощь приветствуется.

Ответы [ 3 ]

2 голосов
/ 23 декабря 2010

Первое, что вы должны сделать, это избавиться от всех этих ненужных обратных слешей. Некоторые из них должны быть просто удалены; например, обратная косая черта в \"" просто игнорируется. Остальные обратные слеши теряют вес, но вам не нужно каждый раз их выписывать. Например, это будет соответствовать экранированным кавычкам и обратным слешам плюс escape-последовательности пробелов (к вашему сведению, вы оставили t вне своего регулярного выражения):

@"\\[""\\/bfnrt]"

Я пропустил u для выходов Unicode, потому что за ним должны следовать четыре шестнадцатеричные цифры; Вы должны сопоставлять их отдельно от других побегов. Добавление их к приведенному выше регулярному выражению дает вам

@"\\(?:[""\\/bfnrt]|u[0-9A-Fa-f]{4})"

Наконец, вы, похоже, используете [^(""|\\)] для части catch-all, то есть любого символа Юникода, кроме кавычки, обратной косой черты или управляющего символа. На самом деле эта часть соответствует любому символу Юникода, кроме (, ", |, ) или обратной косой черты. Правильный способ сопоставления чего-либо, кроме кавычки или обратной косой черты, будет [^""\\], но вам также необходимо исключить управляющие символы. Для этого вы можете использовать свойство Unicode, \p{Cc}. Вот и все:

@"""(?:[^\p{Cc}""\\]+|\\(?:[""\\/bfnrt]|u[0-9A-Fa-f]{4}))*"""

Обратите внимание, что в это регулярное выражение я включил разделители кавычек, а не добавил их на отдельном шаге, как вы. Я предполагаю, что обратный слеш в \" не должен рассматриваться как буквальный символ; в противном случае вы бы использовали два из них.

2 голосов
/ 23 декабря 2010

Если бы я писал парсер, я мог бы подойти к нему немного по-другому. Синтаксический анализ - это другой вид операции, нежели сопоставление, и иногда Regex может привести вас только на полпути. Например, я бы, вероятно, сопоставил бы и захватил все пары имя / значение из родительского документа JSON, используя регулярное выражение вроде этого: string pattern = @"(?:""[^""\\]*(?:\\.[^""\\]*)*"")+";, которое будет возвращать все между, включая открывающие и закрывающие кавычки строки. Затем я проверил бы захваченную строку на предмет исключительных случаев, описанных в спецификации JSON, таких как обратная косая черта, за которой не следует допустимый escape-код, и затем вывел бы исключение, если я обнаружил какие-либо проблемы. Я мог бы также рассмотреть возможность замены любых открытых кодов перехода, например символа табуляции, на \t. Как только я обработал захваченную строку и проверил ошибки, я мог запустить Regex.Unescape(), чтобы вернуть окончательную строку.

0 голосов
/ 23 декабря 2010

Обратите внимание, что с символами @ две двойные кавычки ("") необходимы для указания одиночной двойной кавычки (") в действительном строковом значении.

Дополнительнок этому, в строке @ -ed символ обратной косой черты буквальный обратный слэш * 1006. * Так что если вы напишите, скажем, @"\\t", механизм регулярных выражений будет искать обратную косую черту, за которой следует буква «t»не символ табуляции.

Я подозреваю, что эти лишние обратные слеши являются источником вашей проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...