Привет,Хабр!Меня зовут Владимир, работаю в 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.
constsimpleKeysTransform=value=>{returnObject.entries(value).reduce((acc, [key,value]) => {constnewKey=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).При надобности, вы уже сами сможете с ними справиться.