2013-07-22 2 views
2

Я реализую какой-то парсер, и мне нужно найти и десериализовать объект json , встроенный в другие полуструктурированные данные. Я использовал регулярное выражение:Regex для соответствия вложенным объектам json

\\{\\s*title.*?\\} 

найти объект

{title:'Title'} 

, но он не работает с вложенными объектами, потому что выражение соответствует только первым нашел закрывающую скобку. Для

{title:'Title',{data:'Data'}} 

он соответствует

{title:'Title',{data:'Data'} 

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

Update:

Чтобы было ясно, что это попытка извлечь данные в формате JSON из слабоструктурированных данных, таких как HTML + JS с вложенным JSON. Я использую GSon JAVA lib для фактического анализа извлеченного JSON.

+0

Остерегайтесь «OMG, не используйте Regex, это eevil!» – SmokeyPHP

+0

.. но со всей серьезностью - почему? Каковы данные, которые вам нужны, и что вам нужно для достижения этого? – SmokeyPHP

+3

@ViktorStolbin Есть готовые аналитические библиотеки JSON. Кроме того, поскольку JSON не является обычным языком, он не может быть правильно разобран регулярными выражениями (точно так же, как HTML). –

ответ

1

Благодаря @Sanjay T. Sharma, который указал мне на «согласование фигур», потому что в конечном итоге я получил некоторое представление о жадных выражениях, а также благодаря другим словам, изначально говорящим, что я не должен делать. К счастью, оказалось, что это нормально, чтобы использовать жадный вариант выражения

\\{\s*title.*\\} 

, потому что нет никаких данных, не JSON между закрывающих скобок.

3

Как и другие, предложенный полноразмерный анализатор JSON - это, вероятно, путь. Если вы хотите, чтобы соответствовать пар ключ-значение в простых примерах, что у вас есть выше, вы можете использовать:

(?<=\{)\s*[^{]*?(?=[\},]) 

Для входной строки

{title:'Title', {data:'Data', {foo: 'Bar'}}} 

Это соответствует:

1. title:'Title' 
2. data:'Data' 
3. foo: 'Bar' 
+0

Я должен попробовать! Спасибо! –

0

Это абсолютно ужасно, и я не могу поверить, что на самом деле я помещаю свое имя в это решение, но не мог ли вы найти первый символ {, который находится в блоке Javascript, и попытаться проанализировать оставшиеся символы через соответствующую библиотеку разбора JSON? Если это сработает, у вас будет матч. Если это не так, продолжайте читать до следующего символа { и начните сначала.

Есть несколько вопросов, но они, вероятно, можно было обойти:

  • вы должны быть в состоянии идентифицировать Javascript блоков. Большинство языков имеют библиотеки HTML для DOM (я большой поклонник Cyberneko для Java), что позволяет сфокусироваться на блоках <script>...</script>.
  • ваша библиотека разбора JSON должна прекратить употреблять символы из потока, как только она обнаруживает ошибку, и она должна не закрывать поток, когда это происходит.

Улучшение будет после того, как вы нашли первый {, искать совпадающим } один (простой счетчик, который увеличивается на единицу каждый раз, когда вы нашли { и декрементируется, когда вы найдете } должны сделать трюк). Попытайтесь проанализировать полученную строку как JSON. Итерайте до тех пор, пока это не сработает, или у вас закончились вероятные блоки.

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

+0

Справа. это уродливо и не просто реализовать. –