Как избежать лишних строк в Ruby JSON.pretty_generate - PullRequest
0 голосов
/ 13 октября 2019

Я хотел бы создать JSON в следующем формате:

{
   "a": {
       "b": 1
   },
   "c": [
       2
   ],
   "d": [],
   "e": {}
}

Это легко сделать с помощью стандартной поддержки JSON в Python, JavaScript и Go.

В Ruby яУ меня проблемы с получением точного вывода:

$ ~/.rbenv/versions/2.6.3/bin/irb 
irb(main):001:0> require 'json'
=> true
irb(main):002:0> puts JSON.pretty_generate({"a" => {"b" => 1}, "c" => [2], "d" => [], "e" => {}})
{
  "a": {
    "b": 1
  },
  "c": [
    2
  ],
  "d": [

  ],
  "e": {
  }
}
=> nil

Проблемы:

  • Пустые объекты отображаются в две строки.
  • Пустые массивы отображаются в три(!) строки.

Есть ли простой способ получить стандартную поддержку JSON в Ruby для вывода нужного мне результата?

Ответы [ 2 ]

1 голос
/ 14 октября 2019

Я не уверен, если это возможно, хотя варианты, но вот регулярное выражение, которое достигает того, что вы хотите.

structure = {
  "a" => {"b" => 1},
  "c" => [2],
  "d" => [],
  "e" => {}, 
  "f" => "string with [     ] and {       }"
}
json = JSON.pretty_generate(structure)

regex = /(?<content>"(?:[^\\"]|\\.)+")|(?<open>\{)\s+(?<close>\})|(?<open>\[)\s+(?<close>\])/m
puts json.gsub(regex, '\k<open>\k<content>\k<close>')
# {
#   "a": {
#     "b": 1
#   },
#   "c": [
#     2
#   ],
#   "d": [],
#   "e": {},
#   "f": "string with [     ] and {       }"
# }
#=> nil

Используемое регулярное выражение начинает совпадать либо с ", [или { символ.

Если он начинает совпадать с ", он будет совпадать до конца строки, игнорируя все промежуточные значения. Захват всей строки в группе content. Группы open и close будут пустыми. При замене на gsub вся группа content будет возвращена обратно. Это делается для отмены { и [ символов в строковом контексте.

Если он начинает совпадение с [ или {, он допускает только пробельные символы и ищет соответствующие ] или}. Открывающий и закрывающий символы будут помещены в группы open и close соответственно, промежуточный пробел не будет захвачен. Группа content будет пустой. Только группы open и close будут помещены обратно при замене (удаление пробельных символов).

Вот схема соответствия. Он не любил именованные группы, поэтому я удалил их, чтобы отобразить диаграмму. group #1 соответствуют content, group #2 и group #4 соответствуют open, group #3 и group #5 соответствуют close.

regex diagram

0 голосов
/ 13 октября 2019

Невозможно использовать стандартную библиотеку Ruby JSON. JSON.pretty_generate использует JSON.generate с предопределенной конфигурацией:

JSON::PRETTY_STATE_PROTOTYPE.to_hash
{:indent=>"  ",
 :space=>" ",
 :space_before=>"",
 :object_nl=>"\n",
 :array_nl=>"\n",
 :allow_nan=>false,
 :ascii_only=>false,
 :max_nesting=>100,
 :depth=>0,
 :buffer_initial_length=>1024}

Вы можете попробовать:

puts JSON.pretty_generate(object, array_nl: '')
{
  "a": {
    "b": 1
  },
  "c": [    2  ],
  "d": [  ],
  "e": {
  }
}

Я знаю, что это не совсем то, что вы хотите, но используя JSON.generate, вы можете настроить генерацию вывода JSON только в такой степени. Не существует отдельной конфигурации для пустых объектов / массивов. Кроме того, это реализовано в C, так что патч обезьяны не будет работать.

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