логотип PurpleSchool
логотип PurpleSchool

Работа с JSON данными в приложениях Vue

Автор

Олег Марков

Введение

JSON — один из самых популярных форматов обмена данными между клиентом и сервером. Во фронтенд-разработке, особенно при создании SPA на Vue, вы регулярно сталкиваетесь с тем, что нужно получать, парсить, отображать и отправлять такие данные. Работа с JSON лежит в основе интеграции с бекендом, построения динамических интерфейсов, написания форм, списков и многого другого.

В этой статье я расскажу, как обрабатывать JSON в ваших Vue-приложениях. Вы узнаете, как получать и отправлять JSON с помощью fetch и axios, разбирать и сериализовать объекты через методы parse и stringify, эффективно отображать данные в шаблонах и строить реактивные структуры данных. Приведу подробные примеры и поясню, как избежать типичных ошибок.


Работа с JSON: ключевые подходы в Vue

Способы получения JSON-данных во Vue

Vue не предоставляет встроенных средств для получения данных по HTTP, но экосистема позволяет выбрать удобную библиотеку — например, fetch API или axios. Рассмотрим оба варианта.

Получение JSON с помощью fetch

Fetch — современный стандарт работы с HTTP в браузере. Пример запроса:

export default {
  data() {
    return {
      users: [],
      loading: false,
      error: null,
    }
  },
  methods: {
    async fetchUsers() {
      this.loading = true
      this.error = null
      try {
        // Выполняем GET-запрос по url
        const response = await fetch('https://jsonplaceholder.typicode.com/users')
        // Проверяем успешность ответа
        if (!response.ok) throw new Error('Ошибка запроса')
        // Парсим ответ в JSON
        this.users = await response.json()
      } catch (err) {
        this.error = err.message
      } finally {
        this.loading = false
      }
    }
  },
  mounted() {
    // Загружаем данные при инициализации компонента
    this.fetchUsers()
  }
}

Здесь после получения ответа мы используем await response.json() для преобразования потока данных в JavaScript-объект.

Использование axios для работы с JSON

Axios — популярная библиотека, известная простым API и обработкой ошибок. Пример запроса:

import axios from 'axios'

export default {
  data() {
    return {
      posts: [],
      error: null,
    }
  },
  async mounted() {
    try {
      const response = await axios.get('https://jsonplaceholder.typicode.com/posts')
      // Данные автоматически парсятся в JS-объект
      this.posts = response.data
    } catch (err) {
      this.error = err.message
    }
  }
}

Axios сам преобразует JSON-ответы в объекты. Он удобен для работы с REST API и более устойчив к особенностям кросс-доменных запросов.

Парсинг и сериализация JSON

Разбор строк в объекты: JSON.parse

Иногда API возвращает не javascript-объект, а строку в формате JSON. В этом случае используйте JSON.parse, чтобы превратить строку в объект.

const jsonString = '{"id": 1, "name": "Алексей"}'
const user = JSON.parse(jsonString) // user теперь JS-объект

Если структура данных не соответствует ожиданиям, возможны ошибки. Поэтому хорошо использовать try...catch:

try {
  const data = JSON.parse(apiResponse)
} catch (err) {
  // Если API вернул некорректный JSON — обработайте ошибку
  this.error = 'Некорректные данные: ' + err.message
}

Преобразование объектов в строки JSON: JSON.stringify

Когда отправляете данные на сервер (например, с помощью POST), объекты нужно сериализовать:

const newUser = { name: 'Иван', age: 30 }
const requestBody = JSON.stringify(newUser)

Смотрите, теперь объект превращается в строку. Эту строку вы передаёте в теле запроса.

Отправка JSON-данных на сервер

С помощью fetch

POST-запрос с JSON-телом через fetch выглядит так:

async function submitForm() {
  const formData = { name: 'Олег', email: 'oleg@gmail.com' }
  try {
    const response = await fetch('/api/users', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json' // обязательный заголовок!
      },
      body: JSON.stringify(formData)
    })
    // Обработка ответа от сервера
    const result = await response.json()
    console.log(result)
  } catch (error) {
    console.error('Ошибка отправки:', error)
  }
}

Здесь мы сериализуем объект и обязательно передаём заголовок Content-Type.

С помощью axios

Axios упрощает отправку JSON:

async function saveUser(user) {
  try {
    // Второй аргумент axios автоматически сериализует объект
    const response = await axios.post('/api/users', user)
    console.log('Ответ:', response.data)
  } catch (error) {
    console.error('Ошибка:', error)
  }
}

Axios сам выставляет заголовок и сериализует объект.


Использование JSON-данных во Vue-компонентах

Теперь покажу, как удобно работать с вложенными структурами и списками, а также как строить реактивные списки.

Преобразование и выделение нужных данных

Рассмотрим ситуацию, когда сервер присылает вам сложный JSON. Например, список товаров, у которых есть вложенные характеристики:

// Пример ответа API
const response = [
  {
    id: 1,
    name: 'Кофеварка',
    specs: { color: 'черный', volume: 1000 }
  },
  {
    id: 2,
    name: 'Тостер',
    specs: { color: 'белый', slots: 2 }
  }
]

Теперь, чтобы получить список только названий товаров:

const productNames = response.map(item => item.name)
// ['Кофеварка', 'Тостер']

А если надо отобразить их в шаблоне:

<template>
  <div>
    <h2>Список товаров</h2>
    <ul>
      <li v-for="product in products" :key="product.id">
        {{ product.name }} — Цвет: {{ product.specs.color }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      products: []
    }
  },
  async mounted() {
    const resp = await fetch('/api/products')
    this.products = await resp.json()
  }
}
</script>

Обратите внимание: если какое-то свойство может отсутствовать, используйте опциональную цепочку (product.specs?.color) или делайте проверки.

Динамическое изменение и отправка JSON-данных из форм

Рассмотрим, как собрать данные из v-model, обработать их и отправить в формате JSON.

<template>
  <form @submit.prevent="submitData">
    <input v-model="form.name" placeholder="Имя" />
    <input v-model="form.email" placeholder="E-mail" />
    <button type="submit">Отправить</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '',
        email: ''
      }
    }
  },
  methods: {
    async submitData() {
      try {
        const payload = JSON.stringify(this.form)
        // Отправляем POST-запрос
        const response = await fetch('/api/submit', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: payload
        })
        const result = await response.json()
        console.log('Ответ сервера:', result)
      } catch (error) {
        console.error('Ошибка:', error)
      }
    }
  }
}
</script>

Такой подход позволяет преобразовывать любые формы в сериализованные JSON-объекты для отправки.

Рендеринг вложенных JSON-структур

Давайте рассмотрим, как корректно показать вложенные объекты и массивы, если например, у товара есть список тегов или доступных опций:

<template>
  <ul>
    <li v-for="product in products" :key="product.id">
      {{ product.name }}
      <ul>
        <li v-for="tag in product.tags" :key="tag">{{ tag }}</li>
      </ul>
    </li>
  </ul>
</template>

<script>
export default {
  data() {
    return {
      products: [
        { id: 1, name: 'Чайник', tags: ['акция', 'кухня'] },
        { id: 2, name: 'Блендер', tags: ['скидка'] }
      ]
    }
  }
}
</script>

Здесь мы проходим по основному списку и выводим дополнительную вложенную информацию. Такой способ раскрытия структуры удобен при отображении сложных данных.

Реактивность при изменениях JSON

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

// Это добавит новое свойство, но не всегда будет реактивным
this.someObj.newProp = 'value'

// Правильный способ:
this.$set(this.someObj, 'newProp', 'value') // Vue 2
// или напрямую, если данные определены заранее (Vue 3)

Старайтесь инициализировать все необходимые поля на старте.


Особенности обработки ошибок и работы с невалидным JSON

Работая с API, вы можете столкнуться с поврежденными или неожиданными данными. Лучшие практики:

  • Всегда используйте try...catch при работе с JSON.parse
  • Проверяйте типы и структуру данных перед тем, как их использовать
  • Можно заранее описать типы с помощью TypeScript или валидировать данные вручную:
function isValidUser(obj) {
  return obj && typeof obj.name === 'string' && typeof obj.age === 'number'
}

Универсальный пример комплексной работы с JSON во Vue

Объединим все шаги: сформируем компонент, который загружает, преобразует, отображает и отправляет данные, написанные в форме.

<template>
  <div>
    <h2>Пользователи</h2>
    <ul>
      <li v-for="user in users" :key="user.id">
        {{ user.name }} ({{ user.email }})
      </li>
    </ul>
    <form @submit.prevent="addUser">
      <input v-model="newUser.name" placeholder="Имя" required />
      <input v-model="newUser.email" placeholder="E-mail" required />
      <button type="submit">Добавить пользователя</button>
    </form>
    <div v-if="error" class="error">{{ error }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      users: [],
      newUser: { name: '', email: '' },
      error: null
    }
  },
  async mounted() {
    try {
      const resp = await fetch('/api/users')
      this.users = await resp.json()
    } catch (e) {
      this.error = 'Ошибка загрузки пользователей'
    }
  },
  methods: {
    async addUser() {
      try {
        const response = await fetch('/api/users', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(this.newUser)
        })
        const created = await response.json()
        this.users.push(created)
        this.newUser = { name: '', email: '' }
      } catch (e) {
        this.error = 'Не удалось добавить пользователя'
      }
    }
  }
}
</script>

Здесь соединены все основные этапы: загрузка данных GET-запросом, сериализация и отправка данных POST-запросом, реактивное обновление списка.


Загрузка статического JSON локально

Иногда данные находятся не на сервере, а прямо в проекта: например, в рамках локального тестирования или настроек.

Вариант 1 (Vue CLI): поместите файл data.json в папку public. js const resp = await fetch('/data.json') const data = await resp.json()

Вариант 2 (импорт через import):

import products from '../data/products.json' // Webpack или Vite поддерживают такое

export default {
  data() {
    return { products }
  }
}

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


Особые приемы и лучшие практики

Обработка больших JSON массиво

Если вы работаете с большими данными, разбивайте их на порции, поддерживайте пагинацию, старайтесь не хранить гигантские объекты в памяти.

Сохранение и загрузка JSON в localStorage

Чтобы кэшировать пользовательские данные:

const key = 'user-profile'
// Сохраняем объект в localStorage
localStorage.setItem(key, JSON.stringify(profile))
// Загружаем
const loaded = JSON.parse(localStorage.getItem(key))

Использование сторонних утилит для валидации JSON

Для проверки структуры используйте joi, ajv, yup и другие валидаторы.


Заключение

Работа с JSON-данными является повседневной задачей при создании современных Vue-приложений. Вы научились получать и парсить ответы API, сериализовать объекты, отправлять данные через HTTP-запросы и отображать их во Vue-компонентах. Примеры кода иллюстрируют основные подходы к взаимодействию с вложенными и сложными структурами JSON, а также показывают, как обеспечить реактивность и защититься от ошибок.

Если применять эти принципы, интеграция с внешними сервисами, создание динамических списков и форм станет значительно проще и надежнее.


Частозадаваемые технические вопросы по работе с JSON в Vue

Как обработать массив внутри JSON, если у некоторых элементов отсутствуют нужные поля?

Используйте опциональную цепочку или проверки наличия:
js items.forEach(item => { const name = item?.name || 'Неизвестно' }) Это исключит ошибку доступа к несуществующим данным.

Как обновить объект внутри массива реактивно после загрузки из JSON?

В Vue 3 просто изменяйте нужный индекс: js this.users[index] = { ...this.users[index], name: 'Новое имя' } В Vue 2 лучше использовать Vue.set: js this.$set(this.users, index, обновленныйОбъект)

Почему после изменения вложенного массива не обновляется шаблон?

Vue отслеживает только те поля, что были объявлены заранее. Если вы добавили новое поле или вложенный массив после инициализации, убедитесь что структура данных объявлена в data или используйте $set для добавления.

Как получить только определенные поля из большого JSON-объекта?

Сделайте трансформацию с помощью map: js const usersShort = users.map(({ name, email }) => ({ name, email })) Это создаст новый массив с только нужными полями.

Как отправить массив или объект с вложенными структурами на сервер?

Сериализуйте через JSON.stringify: js const complexData = [{ a: 1 }, { b: 2 }] fetch('/api/data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(complexData) }) Сервер примет JSON в виде строки и сможет декодировать структуру.

Стрелочка влевоИспользование query-параметров и их обработка в маршрутах VueПолучение данных и API-запросы во Vue.jsСтрелочка вправо

Все гайды по Vue

Работа с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueОбзор популярных шаблонов и стартовых проектов на VueКак организовать страницы и маршруты в проекте на VueСоздание серверных приложений на Vue с помощью Nuxt jsРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияНастройка и сборка проектов Vue с использованием современных инструментов
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование метода map в Vue для обработки массивовОбработка пользовательского ввода в Vue.jsОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitИспользование директив и их особенности на Vue с помощью defineСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в Vue
Открыть базу знаний