Created
April 25, 2025 09:42
-
-
Save sunmeat/081815f93a2f08ef6f9ca770fd06bc58 to your computer and use it in GitHub Desktop.
пример реальной работы с API и JSON (синхронный подход)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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