Автоматически преобразовывать хэш-ключи в camelCase в JBuilder

Я использую JBuilder версии 2.4.1 и Rails 4.2.6. Я пытаюсь сериализовать сложный объект в JSON. Код выглядит следующим образом:

json.key_format! camelize: :lower

json.data_object @foo

@foo выглядит так:

{
  key: 'value',
  long_key: 'value'
}

Я ожидаю, что это будет отображаться как

{
  "dataObject": {
    "key": "value",
    "longKey": "value"
  }
}

Но вместо этого он сохраняет исходные хеш-ключи, только преобразовывая data_object в camelCase.

{
  "dataObject": {
    "key": "value",
    "long_key": "value"
  }
}

Итак, вопрос в следующем: как правильно преобразовать хэш-ключи в верблюжью форму с помощью JBuilder?


person Morozzzko    schedule 01.06.2016    source источник
comment
Просто упомянем, что у jbuilder теперь есть Jbuilder.deep_format_keys true, который делает именно то, что вы хотите. Я знаю, что это старый пост, но я смог его найти, и я, вероятно, не единственный :)   -  person Entilore    schedule 14.07.2021


Ответы (3)


Как уже упоминал Брайс, Jbuilder использует to_json вместо обработки хеша.

Простое решение — использовать json.set! для сериализации хэша вручную.

json.key_format! camelize: :lower

json.data_object do
  @foo.each do |key, value|
    json.set! key, value
  end
end

Хотя есть проблема: если @foo пуст, он вообще не создаст объект. Вот решения, которые я нашел:

  1. Определите пустой хеш перед сериализацией

    json.key_format! camelize: :lower
    
    json.data_object({}) # don't forget parentheses or Ruby will handle {} as a block 
    
    json.data_object do
      @foo.each do |key, value|
        json.set! key, value
      end
    end
    
  2. Сериализация пустого хэша, если исходная переменная пуста

    json.key_format! camelize: :lower
    
    if (@foo.empty?) do 
      json.data_object({})
    else 
      json.data_object do
        @foo.each do |key, value|
          json.set! key, value
        end
      end
    end
    

    Или, если вы предпочитаете, чтобы ваш код был плоским

    json.key_format! camelize: :lower
    
    json.data_object({}) if @foo.empty?
    
    json.data_object do
      @foo.each do |key, value|
        json.set! key, value
      end
    end unless @foo.empty?
    

Однако эти решения не будут работать, если вам нужно сериализовать вложенные объекты. Вы можете добиться глубокой сериализации, исправив объект json внутри Jbuilder.

def json.hash!(name, hash)
  if hash.empty?
    set! name, {}
  else
    set! name do
      hash.each do |key, value|
        if value.is_a?(Hash)
          hash! key, value
        else
          set! key, value
        end
      end
    end
  end
end

Тогда можно просто использовать json.hash! :data_object, @foo и получить желаемый результат.

person Morozzzko    schedule 06.06.2016

Попробуйте установить это глобально в своем приложении (например, config/environment.rb)

Jbuilder.key_format camelize: :lower
person beaorn    schedule 01.06.2016
comment
Я получаю тот же результат. Он не будет отображать хэш-ключи - person Morozzzko; 01.06.2016
comment
Хм, я уверен, что вы это сделали, но вы перезапустили свой сервер rails после добавления этого, верно? Вы также уверены, что jbuilder отображает шаблон JSON, а rails не просто возвращается к to_json? Возможно, вам придется изучить создание массива хэшей, загруженных в json.array rubydoc.info /github/rails/jbuilder/Jbuilder:массив! - person beaorn; 01.06.2016
comment
Да, я перезапустил его. Даже сделал это несколько раз, просто для уверенности. Я не совсем уверен насчет to_json. Я был бы рад, если бы вы могли объяснить это. В настоящее время у меня есть обходной путь с использованием циклов, который я опубликую, если никто не найдет лучшего решения. - person Morozzzko; 01.06.2016
comment
Мне все еще кажется, что по умолчанию используется рендеринг с использованием to_json и обход Jbuilder, поэтому преобразование camelize не применяется. github.com/rails/jbuilder/issues/236 - person beaorn; 01.06.2016

Я не уверен, что это все еще актуально. Но для тех, кто все еще ищет элегантное решение, я рекомендую взглянуть на:

https://github.com/vigetlabs/olive_branch

Этот гем позволяет пользователям вашего API передавать и получать ключи в верблюжьем или тире, в то время как ваше приложение Rails получает и создает ключи в змеином регистре.

Вот пост, в котором автор объясняет идею этого драгоценного камня. https://www.viget.com/articles/introduction-olivebranch/

Надеюсь, поможет

person Sergio Azevedo    schedule 22.02.2018