Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Created April 25, 2025 09:42
Show Gist options
  • Save sunmeat/081815f93a2f08ef6f9ca770fd06bc58 to your computer and use it in GitHub Desktop.
Save sunmeat/081815f93a2f08ef6f9ca770fd06bc58 to your computer and use it in GitHub Desktop.
пример реальной работы с API и JSON (синхронный подход)
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<title>Расширенная работа с API и JSON</title>
<style>
body {
font-family: monospace;
background-color: #111;
color: #0ff;
padding: 2rem;
}
h1, h2 {
text-align: center;
}
ul {
background-color: #222;
padding: 1rem;
border-radius: 8px;
list-style: none;
}
li {
margin: 0.5rem 0;
}
pre {
background-color: #222;
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
background-color: #222;
margin: 1rem 0;
}
th, td {
border: 1px solid #0ff;
padding: 0.5rem;
text-align: left;
}
img {
width: 50px;
vertical-align: middle;
}
.filter {
margin: 1rem 0;
background-color: #333;
padding: 0.5rem;
border-radius: 8px;
}
input {
background-color: #111;
color: #0ff;
border: 1px solid #0ff;
padding: 0.3rem;
}
</style>
</head>
<body>
<h1>PokeAPI</h1>
<div class="filter">
<label>Фильтр по имени: <input type="text" id="nameFilter" placeholder="Введите имя"></label>
</div>
<table id="pokemonTable">
<thead>
<tr>
<th>Изображение</th>
<th>Имя</th>
<th>Типы</th>
<th>Рост (дм)</th>
<th>Вес (кг)</th>
<th>Способности</th>
</tr>
</thead>
<tbody id="pokemonList"></tbody>
</table>
<h2>JSON-данные</h2>
<pre id="output"></pre>
<h2>Фильтрованные JSON-данные</h2>
<pre id="filteredOutput"></pre>
<script>
class Pokemon {
constructor(data) {
this.id = data.id;
this.name = data.name;
this.height = data.height;
this.weight = data.weight;
this.types = data.types;
this.abilities = data.abilities;
this.sprite = data.sprites?.front_default;
}
// кастомная сериализация в JSON
toJSON() {
return {
id: this.id,
name: this.name,
height: `${this.height} дм`,
weight: `${this.weight} кг`,
types: this.types.map(type => type.type.name),
abilities: this.abilities.map(ability => ability.ability.name),
sprite: this.sprite
};
}
}
// синхронный GET-запрос
function fetchData(url) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, false); // третий параметр: асинхронный запрос или нет
xhr.send();
if (xhr.status === 200) {
return JSON.parse(xhr.responseText);
} else {
throw new Error(`Ошибка загрузки ${url}: ${xhr.status}`);
}
}
// отображение покемонов в таблице
function renderPokemons(pokemons, container) {
container.innerHTML = ''; // Очищаем таблицу
pokemons.forEach(pokemon => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td><img src="${pokemon.sprite}" alt="${pokemon.name}"></td>
<td>${pokemon.name}</td>
<td>${pokemon.types.map(type => type.type.name).join(', ')}</td>
<td>${pokemon.height}</td>
<td>${pokemon.weight}</td>
<td>${pokemon.abilities.map(ability => ability.ability.name).join(', ')}</td>
`;
container.appendChild(tr);
});
}
// получение и обработка данных
function fetchPokemons() {
const pokemonNames = ['pikachu', 'beedrill']; // поиск конкретных покемонов
const pokemons = [];
try {
// запрос на получение двух конкретных покемонов
pokemonNames.forEach(name => {
const data = fetchData(`https://pokeapi.co/api/v2/pokemon/${name}`);
pokemons.push(new Pokemon({
id: data.id,
name: data.name,
height: data.height,
weight: data.weight,
types: data.types,
abilities: data.abilities,
sprites: data.sprites
}));
});
// запрос первых пяти из 1302
const listData = fetchData('https://pokeapi.co/api/v2/pokemon?limit=5');
listData.results.forEach(pokemon => {
if (!pokemonNames.includes(pokemon.name)) { // Избегаем дублирования
const data = fetchData(pokemon.url);
pokemons.push(new Pokemon({
id: data.id,
name: data.name,
height: data.height,
weight: data.weight,
types: data.types,
abilities: data.abilities,
sprites: data.sprites
}));
}
});
// отображение в таблице
const pokemonList = document.getElementById('pokemonList');
renderPokemons(pokemons, pokemonList);
// сериализация всех данных в JSON
const jsonString = JSON.stringify(pokemons, null, 2);
document.getElementById('output').textContent = jsonString;
// кастомный replacer для JSON.stringify
const customJson = JSON.stringify(pokemons, (key, value) => {
if (key === 'height' || key === 'weight') {
return `Formatted: ${value}`;
}
return value;
}, 2);
console.log('Кастомный JSON:', customJson);
// десериализация с reviver
const parsedPokemons = JSON.parse(jsonString, (key, value) => {
if (key === 'name') {
return value.toUpperCase();
}
return value;
});
console.log('Распарсенные покемоны с преобразованием:', parsedPokemons);
// фильтрация данных (например, электрические покемоны)
const electricPokemons = pokemons.filter(pokemon =>
pokemon.types.some(type => type.type.name === 'electric')
);
document.getElementById('filteredOutput').textContent =
JSON.stringify(electricPokemons, null, 2);
// текстовое поле частичного поиска по имени
const nameFilter = document.getElementById('nameFilter');
nameFilter.addEventListener('input', () => {
const filterValue = nameFilter.value.toLowerCase();
const filteredPokemons = pokemons.filter(pokemon =>
pokemon.name.toLowerCase().includes(filterValue)
);
renderPokemons(filteredPokemons, pokemonList);
document.getElementById('filteredOutput').textContent =
JSON.stringify(filteredPokemons, null, 2);
});
// тест корректности JSON
try {
const validJson = '{"name": "Пикачу", "type": "electric"}';
const testParse = JSON.parse(validJson);
console.log('Тестовый JSON распарсен:', testParse);
// Проверка структуры JSON
if (!testParse.name || !testParse.type) {
throw new Error('JSON не содержит обязательных полей');
}
console.log('Структура JSON корректна');
} catch (error) {
console.error('Ошибка проверки JSON:', error.message);
}
} catch (error) {
console.error('Ошибка обработки данных:', error.message);
document.getElementById('output').textContent = 'Ошибка обработки данных: ' + error.message;
}
}
fetchPokemons();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment