Разбор JSON без ключей в кавычках - PullRequest
23 голосов
/ 14 января 2010

Я понимаю, что в JSON ключи должны заключаться в двойные кавычки. Тем не менее, я использую источник данных, который не заключает их в кавычки, что приводит к возникновению ошибки в синтаксическом анализаторе Ruby JSON. Есть ли способ выполнить «нестрогий» анализ?

Пример:

>> JSON.parse('{name:"hello", age:"23"}')
JSON::ParserError: 618: unexpected token at '{name:"hello", age:"23"}'
    from /Library/Ruby/Gems/1.8/gems/json-1.1.7/lib/json/common.rb:122:in `parse' 
    from /Library/Ruby/Gems/1.8/gems/json-1.1.7/lib/json/common.rb:122:in `parse'
    from (irb):5
>> JSON.parse('{"name":"hello", "age":"23"}')
=> {"name"=>"hello", "age"=>"23"}
>> 

(я пытался использовать регулярное выражение для добавления кавычек перед синтаксическим анализом, но не смог получить его полностью работоспособным).

Ответы [ 6 ]

16 голосов
/ 14 января 2010

Если данные довольно хорошо сформированы, кроме этого, простое регулярное выражение может сделать это:

irb(main):009:0> '{name:"hello", age:"23"}'.gsub(/([a-z]+):/, '"\1":')
=> "{\"name\":\"hello\", \"age\":\"23\"}"
9 голосов
/ 03 апреля 2013

У меня та же проблема со сторонним фидом данных, но моя возвращает более сложный JSON-подобный ответ, который не обрабатываются решениями gsub. После некоторых исследований оказалось, что эти потоки данных на самом деле являются литералами объектов JavaScript, которые не требуют, чтобы ключи были заключены в кавычки.

Чтобы решить эту проблему, я добавил гем execjs и установил node.js (гем therubyracer, вероятно, тоже подойдет). После завершения следующее возвращает правильно проанализированный хэш ruby.

ExecJS.eval('{name:"hello", age:"23"}')
 => {"name"=>"hello", "age"=>"23"}
7 голосов
/ 14 января 2010

Интересно, что в вашем примере действителен синтаксис ruby ​​1.9 Hash. Если ваши данные действительно так просты (без пробелов или других специальных символов в именах ключей), и вы можете обработать их в безопасном контексте, вы можете просто eval.

irb(main):001:0> eval '{name:"hello", age:"23"}'
=> {:name=>"hello", :age=>"23"}

Это дает вам символы в качестве ключей, поэтому пост-процесс, если вам нужно превратить их в строки:

irb(main):002:0> eval('{name:"hello", age:"23"}').reduce({}) {|h,(k,v)| h[k.to_s] = v; h}
=> {"name"=>"hello", "age"=>"23"}
2 голосов
/ 27 февраля 2010
gsub(/(\w+)\s*:/, '"\1":')

работал лучше, чем

gsub(/([a-z]+):/, '"\1":')

Если в нем были пробелы или заглавные буквы, это не удалось.

1 голос
/ 14 января 2010

(отвечая на мой собственный вопрос) Фрагмент, который разместил Флойд, был похож на то, что я пробовал - он терпел неудачу, потому что некоторые из моих строк содержат двоеточия. Но я упорствовал и нашел решение:

gsub(/([\{|\,}])\s*([a-zA-Z]+):/, '\1 "\2":')
0 голосов
/ 28 февраля 2018

Вот как я должен был это решить:

JSON.parse(broken_json_string.gsub(/'([^']+)':/, '"\1":'))

В некоторых из приведенных выше вариантов предполагается, что ключи содержат только буквы; некоторые из них содержали подчеркивания, пробелы и т. д. Проще сказать «любой символ, который не является одинарной кавычкой» (учитывая, что в нашем случае все ключи были заключены в одинарные кавычки).

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