Более эффективный метод, чем замена строки на ruby ​​gsub - PullRequest
1 голос
/ 10 октября 2019

У меня есть сторонний JSON-канал, который огромен - много данных. Например,

{
   "data": [{
     "name": "ABC",
     "price": "2.50"
   },
   ...
   ]
}

Мне необходимо убрать кавычки из цены, поскольку это требуется для потребителя канала JSON.

Для этого я выполняю регулярное выражение, чтобы найтицены, а затем итерации по ценам и выполнение строки замените с помощью gsub. Вот как я это делаю:

price_strings = json.scan(/(?:"price":")(.*?)(?:")/).uniq
price_strings.each do |price|
  json.gsub!("\"#{price.reduce}\"", price.reduce)
end
json

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

Ответы [ 2 ]

2 голосов
/ 10 октября 2019

Это действительно дурацкое поручение.

JSON.parse('{ "price": 2.50 }')
> {price: 2.5}

Как вы можете видеть из этого примера javascript, парсер на стороне потребителя будет обрезать float до того, что он хочет.

Использовать aСтрока, если вы хотите предоставить отформатированное число или оставить форматирование для клиента.

Фактически, использование чисел с плавающей точкой для представления денег широко известно как очень плохая идея, так как числа с плавающей запятой и двойные числа не могут точно представлять базовые 10, кратныемы используем для денег. JSON имеет только один тип чисел, представляющий как числа с плавающей запятой, так и целые числа.

Если клиент собирается выполнять какие-либо вычисления со значением, вы должны использовать целое число в самой низкой денежной деноминации (центы для евро и долларов)) или строка, которая интерпретируется потребителем как эквивалентный тип BigDecimal.

2 голосов
/ 10 октября 2019

Если эта строка JSON будет сериализована в Hash в какой-то момент в вашем приложении или в другой сторонней зависимости вашего кода (то есть для использования вашими коллегами или модулями), я предлагаю договориться с нимипреобразовать значение цены из String в Numeric по требованию, когда json уже равен Hash, поскольку это более эффективно, и позволяет им ...

... обрабатывать край-случай, где, скажем, "price": "", из которого мой код ниже не будет работать, так как он уберет "" и будет синтаксической ошибкой JSON.

Однако, если вы это сделаетене можете контролировать это, или делаете однократную мутацию для всех данных json, тогда можете попробовать ниже?

json =
<<-eos
{
  "data": [{
    "name": "ABC",
    "price": "2.50",
    "somethingsomething": {
      "data": [{
        "name": "DEF",
        "price": "3.25", "someprop1": "hello",
        "someprop2": "world"
      }]
    },
    "somethinggggg": {
      "price": "123.45" },
    "something2222": {
      "price": 9.876, "heeeello": "world"
    }
  }]
}
eos

new_json = json.gsub /("price":.*?)"(.*?)"(.*?,|})/, '\1\2\3'

puts new_json
# =>
# {
#   "data": [{
#     "name": "ABC",
#     "price": 2.50,
#     "somethingsomething": {
#       "data": [{
#         "name": "DEF",
#         "price": 3.25, "someprop1": "hello",
#         "someprop2": "world"
#       }]
#     },
#     "somethinggggg": {
#       "price": 123.45 },
#     "something2222": {
#       "price": 9.876, "heeeello": "world"
#     }
#   }]
# }

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я не эксперт по регулярным выражениям.

...