Конец вечного противостояния snake_keys VS camelKeys: наводим порядок в стилях написания переменных

Привет, Хабр! Меня зовут Владимир, работаю в Ozon, занимаюсь фронтендом.   

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

Представим ситуацию: начинается работа над сайтом, разработчики тёмной и светлой сторон встречаются обсудить насущные вопросы. Один из таких вопросов связан с передачей данных. 

Бекенд отдает и принимает данные в виде: 

{  		user_name: "user1",  		main_title: "Title",  } 

Фронтенд:

{  		userName: "user1",  		mainTitle: "Title",  } 

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

В этой статье мы попробуем решить эту проблему – преобразовать все данные бэкенда в данные фронтенда и наоборот. Воспользуемся для этого JavaScript. 

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

Шаг 1. Преобразование строки 

Нам поможет встроенная функция replace. Она умеет заменять каждое вхождение заданного регулярного выражения с помощью функции маппера, которую мы передаём вторым аргументом. 

# Преобразование snake_keys строки в camelKeys: 

const snakeToCamel = str => {      return str.replace(/([_][a-z])/g, letter => {          return letter                  .toUpperCase()                  .replace('_', '')      })  } 

# Преобразование camelKeys строки в snake_keys: 

const camelToSnake = str => {      return str.replace(/[A-Z]/g, letter => {          return '_' + letter.toLowerCase()      })  } 

Шаг 2. Работа с объектами 

# Возьмем пример с начала статьи   {  		user_name: "user1",  		main_title: "Title",  } 

Пройдёмся по ключам объекта и заменим их с помощью уже реализованной функции snakeToCamel. 

const simpleKeysTransform = value => {      return Object.entries(value).reduce((acc, [key, value]) => {          const newKey = snakeToCamel(key)                   return {...acc, [newKey]: value}      }, {})  } 

Давайте теперь сделаем универсальную функцию преобразования и будем принимать на вход ещё переменную, отвечающую за изначальный вид стиля ключей объекта.

const keysTransform1 = (value, isInitialSnake = true) => {      const chooseStyle = isInitialSnake ? snakeToCamel : camelToSnake       return Object.entries(value).reduce((acc, [key, value]) => {          const newKey = chooseStyle(key)           return {...acc, [newKey]: value}      }, {})  } 

Шаг 3. Что делать с вложенными объектами 

# Например   {    user_info: {      first_name: "User",      last_name: "Userin”    }  } 

Применим рекурсию. Обернём основную логику в функцию и в ней будем проверять: является ли наше значение объектом. Если да, то будем вызывать нашу функцию снова и снова. 

const keysTransform2 = (input, isInitialSnake = true) => {      const chooseStyle = isInitialSnake ? snakeToCamel : camelToSnake       const recursiveTransform = value => {           if (value && typeof value === 'object') {              return Object.entries(value).reduce((acc, [key, value]) => {                  const newKey = chooseStyle(key)                  const newValue = recursiveTransform(value)                   return {...acc, [newKey]: newValue}              }, {})          }           return value      }       return recursiveTransform(input)  } 

Шаг 4. Что делать с массивами 

# Например   {    users: [      {        first_name: "user1",        phone_number: 8996923      },      {        first_name: "user2",        phone_number: 12312312      }    ]    }  

Всё до безобразия просто. Добавим проверку на массив и на каждый его элемент навесим нашу рекурсивную функцию. 

const keysTransform = (input, isInitialSnake = true) => {       const chooseStyle = isInitialSnake ? snakeToCamel : camelToSnake       const recursiveTransform = value => {          if (Array.isArray(value)) {              return value.map(recursiveTransform)          }           if (value && typeof value === 'object') {              return Object.entries(value).reduce((acc, [key, value]) => {                  const newKey = chooseStyle(key)                  const newValue = recursiveTransform(value)                   return {...acc, [newKey]: newValue}              }, {})          }           return value      }       return recursiveTransform(input)  } 

Перемирие 

Давайте посмотрим, что получилось: мы реализовали алгоритм преобразования ключей объектов из snake_keys в camelKeys и наоборот. Чуть-чуть меньше раздора между фронтендом и бэкендом – неплохо же! 

Существуют и другие стили написания составных слов (PascalKeys, kebab-keys, UPPER_SNAKE_KEYS). При надобности, вы уже сами сможете с ними справиться. 

ссылка на оригинал статьи https://habr.com/ru/company/ozontech/blog/560294/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *