1. What is JSON?
JSON means JavaScript Object Notation. It is a simple text format used to store and transfer data.
When an Angular application talks to a server, the server usually sends JSON. Angular receives that JSON, converts it into JavaScript objects, and displays it in the HTML template.
JSON is data
It contains names, numbers, lists, booleans, and nested objects.
Angular shows data
Angular receives JSON and uses data binding to show it on the page.
| JSON Concept | Example | Angular Usage |
|---|---|---|
| Object | { "name": "Angular" } |
Single course, user, product, post |
| Array | [{...}, {...}] |
List of courses, users, products |
| String | "Champak" |
Names, titles, descriptions |
| Number | 999 |
Price, marks, id, count |
| Boolean | true |
Published, available, active |
| Nested object | { "author": { "name": "Roy" } } |
Address, profile, author, metadata |
provideHttpClient() in application providers, and the HTTP API is provided by
HttpClient from @angular/common/http.
2. Angular Setup
Create a fresh Angular project.
npm install -g @angular/cli
ng new json-processing-demo
cd json-processing-demo
ng serve
ng serve. Open http://localhost:4200.
You should see the Angular application running.
Open the project in Visual Studio Code.
code .
src/app/app.component.ts,
src/app/app.component.html,
src/app/app.component.css,
src/app/app.config.ts.
3. JSON Basics
JSON looks like JavaScript object syntax, but it is stricter.
{
"id": 1,
"title": "Angular JSON Processing",
"price": 499,
"published": true,
"tags": ["Angular", "JSON", "Frontend"],
"author": {
"name": "Champak Roy",
"brand": "Programmer's Picnic"
}
}
Important JSON Rules
- Keys must be inside double quotes.
- String values must be inside double quotes.
- No comments are allowed inside pure JSON.
- No trailing comma is allowed after the last item.
- JSON can contain object, array, string, number, boolean, or null.
{ "name": "Angular", }
4. Inline JSON Data in Angular Component
Before reading external files or APIs, first keep JSON-like data directly inside the component.
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
imports: [],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
course = {
id: 1,
title: 'Angular JSON Processing',
category: 'Angular',
price: 499,
published: true
};
}
<h1>{{ course.title }}</h1>
<p>Category: {{ course.category }}</p>
<p>Price: ₹{{ course.price }}</p>
@if (course.published) {
<p>This course is published.</p>
} @else {
<p>This course is not published yet.</p>
}
5. Interfaces: Give Shape to JSON
TypeScript lets us define the expected shape of JSON data using an interface. This makes Angular code safer and easier to understand.
ng generate interface models/course
src/app/models/course.ts
export interface Course {
id: number;
title: string;
category: string;
price: number;
published: boolean;
}
import { Component } from '@angular/core';
import { Course } from './models/course';
@Component({
selector: 'app-root',
imports: [],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
course: Course = {
id: 1,
title: 'Angular JSON Processing',
category: 'Angular',
price: 499,
published: true
};
}
prize instead of price,
TypeScript can warn you before the application breaks.
6. Display a JSON Array
Most real JSON data comes as an array.
import { Component } from '@angular/core';
import { Course } from './models/course';
@Component({
selector: 'app-root',
imports: [],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
courses: Course[] = [
{
id: 1,
title: 'Angular Data Binding',
category: 'Angular',
price: 299,
published: true
},
{
id: 2,
title: 'Angular JSON Processing',
category: 'Angular',
price: 499,
published: true
},
{
id: 3,
title: 'JavaScript Basics',
category: 'JavaScript',
price: 199,
published: false
}
];
}
<h1>Courses</h1>
@for (course of courses; track course.id) {
<div class="course-card">
<h2>{{ course.title }}</h2>
<p>Category: {{ course.category }}</p>
<p>Price: ₹{{ course.price }}</p>
@if (course.published) {
<p class="published">Published</p>
} @else {
<p class="draft">Draft</p>
}
</div>
}
.course-card {
padding: 18px;
margin: 16px;
border-radius: 16px;
background: #fff7ed;
border: 1px solid #ffcc99;
}
.published {
color: green;
font-weight: bold;
}
.draft {
color: red;
font-weight: bold;
}
@for block loops through a collection and recommends tracking items,
commonly with a unique id.
7. Read Local JSON File
A local JSON file is useful when your website is static, hosted on GitHub Pages, or when you want data to live separately from the component code.
Create a JSON file
Create this folder and file:
public/data/courses.json
public are served directly.
The file public/data/courses.json should be accessible at:
http://localhost:4200/data/courses.json
[
{
"id": 1,
"title": "Angular Data Binding",
"category": "Angular",
"price": 299,
"published": true
},
{
"id": 2,
"title": "Angular JSON Processing",
"category": "Angular",
"price": 499,
"published": true
},
{
"id": 3,
"title": "JavaScript Basics",
"category": "JavaScript",
"price": 199,
"published": false
}
]
To load this file properly, use Angular HttpClient.
8. Enable HttpClient
Angular applications use HttpClient to fetch JSON over HTTP.
In a standalone Angular app, provide it once in app.config.ts.
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient()
]
};
provideHttpClient() as the modern way to provide
HttpClient in application providers.
Load local JSON using HttpClient
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Course } from './models/course';
@Component({
selector: 'app-root',
imports: [],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements OnInit {
courses: Course[] = [];
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get<Course[]>('/data/courses.json')
.subscribe(data => {
this.courses = data;
});
}
}
<h1>Courses from JSON File</h1>
@for (course of courses; track course.id) {
<div class="course-card">
<h2>{{ course.title }}</h2>
<p>Category: {{ course.category }}</p>
<p>Price: ₹{{ course.price }}</p>
</div>
}
http://localhost:4200/data/courses.json. The JSON should appear.
Then open http://localhost:4200. The course cards should appear from the JSON file.
9. Read JSON from an API
An API is a server endpoint that sends data. Angular can read API data in the same way it reads a local JSON file.
this.http.get<Course[]>('https://example.com/api/courses')
.subscribe(data => {
this.courses = data;
});
Using a GitHub Pages JSON URL
For your own static JSON files, you can keep JSON on GitHub Pages and read it in Angular.
jsonUrl = 'https://programmer-s-picnic.github.io/json-images/links/users.json';
ngOnInit() {
this.http.get<any[]>(this.jsonUrl)
.subscribe(data => {
console.log(data);
});
}
10. Loading State and Error Handling
A professional app must show loading messages and errors.
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Course } from './models/course';
@Component({
selector: 'app-root',
imports: [],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements OnInit {
courses: Course[] = [];
loading = true;
errorMessage = '';
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get<Course[]>('/data/courses.json')
.subscribe({
next: data => {
this.courses = data;
this.loading = false;
},
error: error => {
console.error(error);
this.errorMessage = 'Could not load courses. Please try again.';
this.loading = false;
}
});
}
}
@if (loading) {
<p>Loading courses...</p>
}
@if (errorMessage) {
<p class="error">{{ errorMessage }}</p>
}
@if (!loading && !errorMessage) {
@for (course of courses; track course.id) {
<div class="course-card">
<h2>{{ course.title }}</h2>
<p>₹{{ course.price }}</p>
</div>
}
}
.error {
color: white;
background: #b91c1c;
padding: 12px;
border-radius: 10px;
}
/data/wrong-name.json.
You should see the error message.
11. Search and Filter JSON Data
After loading JSON, users often want to search or filter it.
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Course } from './models/course';
@Component({
selector: 'app-root',
imports: [FormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements OnInit {
courses: Course[] = [];
searchText = '';
selectedCategory = 'All';
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get<Course[]>('/data/courses.json')
.subscribe(data => {
this.courses = data;
});
}
get filteredCourses() {
const text = this.searchText.toLowerCase();
return this.courses.filter(course => {
const matchesText =
course.title.toLowerCase().includes(text) ||
course.category.toLowerCase().includes(text);
const matchesCategory =
this.selectedCategory === 'All' ||
course.category === this.selectedCategory;
return matchesText && matchesCategory;
});
}
}
<h1>Course Directory</h1>
<input
[(ngModel)]="searchText"
placeholder="Search course..."
/>
<select [(ngModel)]="selectedCategory">
<option>All</option>
<option>Angular</option>
<option>JavaScript</option>
</select>
<p>Results: {{ filteredCourses.length }}</p>
@for (course of filteredCourses; track course.id) {
<div class="course-card">
<h2>{{ course.title }}</h2>
<p>Category: {{ course.category }}</p>
<p>Price: ₹{{ course.price }}</p>
</div>
}
Angular in the search box. Only Angular courses should remain visible.
12. Sort JSON Data
Sorting means changing the order of displayed JSON items.
sortByPriceLowToHigh() {
this.courses = [...this.courses].sort((a, b) => a.price - b.price);
}
sortByPriceHighToLow() {
this.courses = [...this.courses].sort((a, b) => b.price - a.price);
}
sortByTitle() {
this.courses = [...this.courses].sort((a, b) =>
a.title.localeCompare(b.title)
);
}
<button (click)="sortByPriceLowToHigh()">
Price: Low to High
</button>
<button (click)="sortByPriceHighToLow()">
Price: High to Low
</button>
<button (click)="sortByTitle()">
Sort by Title
</button>
[...this.courses]?
It creates a new array before sorting. This is cleaner and safer than mutating the original array
directly.
13. Nested JSON
Real JSON often contains objects inside objects and arrays inside objects.
{
"id": 1,
"title": "Angular JSON Processing",
"author": {
"name": "Champak Roy",
"website": "learnwithchampak.live"
},
"topics": [
"JSON basics",
"HttpClient",
"Filtering",
"Mini project"
]
}
Interface for Nested JSON
export interface CourseDetail {
id: number;
title: string;
author: {
name: string;
website: string;
};
topics: string[];
}
Display Nested JSON
<h1>{{ course.title }}</h1>
<p>Author: {{ course.author.name }}</p>
<p>Website: {{ course.author.website }}</p>
<h2>Topics</h2>
<ul>
@for (topic of course.topics; track topic) {
<li>{{ topic }}</li>
}
</ul>
14. Add JSON Data from a Form
In the browser, you can add a new object to an existing JSON array. This does not automatically save to the original JSON file, but it updates the current page state.
newCourse: Course = {
id: 0,
title: '',
category: '',
price: 0,
published: true
};
addCourse() {
const courseToAdd: Course = {
...this.newCourse,
id: Date.now()
};
this.courses = [courseToAdd, ...this.courses];
this.newCourse = {
id: 0,
title: '',
category: '',
price: 0,
published: true
};
}
<h2>Add New Course</h2>
<input
[(ngModel)]="newCourse.title"
placeholder="Course title"
/>
<input
[(ngModel)]="newCourse.category"
placeholder="Category"
/>
<input
type="number"
[(ngModel)]="newCourse.price"
placeholder="Price"
/>
<label>
<input
type="checkbox"
[(ngModel)]="newCourse.published"
/>
Published
</label>
<button (click)="addCourse()">Add Course</button>
15. Move JSON Logic to a Service
A service keeps your component clean. The component should focus on UI. The service should handle data loading.
ng generate service services/course
src/app/services/course.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Course } from '../models/course';
@Injectable({
providedIn: 'root'
})
export class CourseService {
private jsonUrl = '/data/courses.json';
constructor(private http: HttpClient) {}
getCourses() {
return this.http.get<Course[]>(this.jsonUrl);
}
}
import { Component, OnInit } from '@angular/core';
import { Course } from './models/course';
import { CourseService } from './services/course.service';
@Component({
selector: 'app-root',
imports: [],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements OnInit {
courses: Course[] = [];
loading = true;
errorMessage = '';
constructor(private courseService: CourseService) {}
ngOnInit() {
this.courseService.getCourses()
.subscribe({
next: data => {
this.courses = data;
this.loading = false;
},
error: error => {
console.error(error);
this.errorMessage = 'Could not load courses.';
this.loading = false;
}
});
}
}
16. Mini Project: JSON Course Directory
Build a full JSON-powered course directory.
Features
- Read courses from
public/data/courses.json. - Show loading message.
- Show error message if JSON fails.
- Display cards using
@for. - Search by title and category.
- Filter by category.
- Sort by price and title.
- Show result count.
Step 1: Course Interface
export interface Course {
id: number;
title: string;
category: string;
level: 'Beginner' | 'Intermediate' | 'Advanced';
price: number;
image: string;
published: boolean;
}
Step 2: JSON Data
[
{
"id": 1,
"title": "Angular Data Binding",
"category": "Angular",
"level": "Beginner",
"price": 299,
"image": "https://angular.io/assets/images/logos/angular/angular.png",
"published": true
},
{
"id": 2,
"title": "Angular JSON Processing",
"category": "Angular",
"level": "Intermediate",
"price": 499,
"image": "https://angular.io/assets/images/logos/angular/angular.png",
"published": true
},
{
"id": 3,
"title": "JavaScript for Absolute Beginners",
"category": "JavaScript",
"level": "Beginner",
"price": 199,
"image": "https://upload.wikimedia.org/wikipedia/commons/6/6a/JavaScript-logo.png",
"published": true
},
{
"id": 4,
"title": "Advanced Frontend Architecture",
"category": "Frontend",
"level": "Advanced",
"price": 999,
"image": "https://angular.io/assets/images/logos/angular/angular.png",
"published": false
}
]
Step 3: Enable HttpClient
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient()
]
};
Step 4: Component Logic
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Course } from './models/course';
@Component({
selector: 'app-root',
imports: [FormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements OnInit {
courses: Course[] = [];
loading = true;
errorMessage = '';
searchText = '';
selectedCategory = 'All';
sortMode = 'title';
constructor(private http: HttpClient) {}
ngOnInit() {
this.loadCourses();
}
loadCourses() {
this.loading = true;
this.errorMessage = '';
this.http.get<Course[]>('/data/courses.json')
.subscribe({
next: data => {
this.courses = data;
this.loading = false;
},
error: error => {
console.error(error);
this.errorMessage = 'Unable to load course JSON.';
this.loading = false;
}
});
}
get categories() {
const categorySet = new Set(this.courses.map(course => course.category));
return ['All', ...Array.from(categorySet)];
}
get filteredCourses() {
const text = this.searchText.toLowerCase().trim();
let result = this.courses.filter(course => {
const matchesSearch =
course.title.toLowerCase().includes(text) ||
course.category.toLowerCase().includes(text) ||
course.level.toLowerCase().includes(text);
const matchesCategory =
this.selectedCategory === 'All' ||
course.category === this.selectedCategory;
return matchesSearch && matchesCategory;
});
if (this.sortMode === 'title') {
result = result.sort((a, b) => a.title.localeCompare(b.title));
}
if (this.sortMode === 'low') {
result = result.sort((a, b) => a.price - b.price);
}
if (this.sortMode === 'high') {
result = result.sort((a, b) => b.price - a.price);
}
return result;
}
}
Step 5: Component HTML
<main class="page">
<section class="hero">
<h1>JSON Course Directory</h1>
<p>Courses loaded from a JSON file in Angular.</p>
</section>
<section class="controls">
<input
[(ngModel)]="searchText"
placeholder="Search by title, category, or level..."
/>
<select [(ngModel)]="selectedCategory">
@for (category of categories; track category) {
<option [value]="category">{{ category }}</option>
}
</select>
<select [(ngModel)]="sortMode">
<option value="title">Sort by title</option>
<option value="low">Price: low to high</option>
<option value="high">Price: high to low</option>
</select>
<button (click)="loadCourses()">Reload JSON</button>
</section>
@if (loading) {
<p class="message">Loading JSON data...</p>
}
@if (errorMessage) {
<p class="error">{{ errorMessage }}</p>
}
@if (!loading && !errorMessage) {
<p class="result-count">
Showing {{ filteredCourses.length }} of {{ courses.length }} courses.
</p>
<section class="course-grid">
@for (course of filteredCourses; track course.id) {
<article class="course-card">
<img [src]="course.image" [alt]="course.title" />
<div class="card-body">
<span class="tag">{{ course.category }}</span>
<h2>{{ course.title }}</h2>
<p>Level: {{ course.level }}</p>
<p class="price">₹{{ course.price }}</p>
@if (course.published) {
<p class="published">Published</p>
} @else {
<p class="draft">Draft</p>
}
</div>
</article>
} @empty {
<p class="message">No matching courses found.</p>
}
</section>
}
</main>
Step 6: Component CSS
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.page {
min-height: 100vh;
padding: 32px;
background: #fff7ed;
font-family: Arial, sans-serif;
color: #1f2937;
}
.hero {
padding: 32px;
border-radius: 24px;
background: linear-gradient(135deg, #ff9933, #ffd6a3);
color: #2a1400;
margin-bottom: 24px;
}
.hero h1 {
margin: 0;
font-size: 42px;
}
.controls {
display: grid;
grid-template-columns: 1fr 220px 220px auto;
gap: 12px;
margin-bottom: 20px;
}
input,
select,
button {
padding: 12px;
border-radius: 12px;
border: 1px solid #d6b17d;
font-size: 16px;
}
button {
background: #ff9933;
color: #1f1300;
font-weight: bold;
cursor: pointer;
}
.course-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 18px;
}
.course-card {
background: white;
border-radius: 20px;
overflow: hidden;
border: 1px solid #ffd0a1;
box-shadow: 0 12px 28px rgba(100, 50, 0, 0.12);
}
.course-card img {
width: 100%;
height: 160px;
object-fit: contain;
background: #fff3e3;
padding: 20px;
}
.card-body {
padding: 18px;
}
.tag {
display: inline-block;
padding: 5px 10px;
border-radius: 999px;
background: #fff3e3;
color: #9a3412;
font-weight: bold;
}
.price {
font-size: 24px;
font-weight: bold;
color: #d96f00;
}
.published {
color: green;
font-weight: bold;
}
.draft {
color: red;
font-weight: bold;
}
.message {
padding: 16px;
background: #eff6ff;
border-left: 6px solid #2563eb;
border-radius: 12px;
}
.error {
padding: 16px;
background: #fee2e2;
border-left: 6px solid #b91c1c;
color: #7f1d1d;
border-radius: 12px;
font-weight: bold;
}
.result-count {
font-weight: bold;
}
@media (max-width: 900px) {
.controls {
grid-template-columns: 1fr;
}
.course-grid {
grid-template-columns: 1fr;
}
.hero h1 {
font-size: 32px;
}
}
ng serve. Open http://localhost:4200.
You should see a saffron-themed JSON course directory with search, category filter,
sorting, result count, and course cards loaded from courses.json.
17. Common Mistakes and Fixes
| Mistake | Reason | Fix |
|---|---|---|
| JSON file shows 404 | Wrong folder or URL | Put file in public/data/file.json and read /data/file.json
|
No provider for HttpClient |
provideHttpClient() missing |
Add it in app.config.ts |
Can't bind to ngModel |
FormsModule missing |
Add imports: [FormsModule] |
| Blank page after JSON load | JSON shape does not match interface/template | Check property names like title, price,
category |
| API blocked | CORS issue | Fix server CORS or use a backend proxy |
| Cannot save to JSON file | Static files are read-only in browser | Use backend, database, or serverless function |
18. Practice Tasks
- Create
students.jsonand display student name, marks, and result. - Create
products.jsonand show product cards. - Add search by product name.
- Add filter by product category.
- Add sort by price.
- Add loading and error messages.
- Create an interface for each JSON file.
- Create a service for loading JSON.
- Show nested JSON such as address, author, or profile.
- Create a course directory from a GitHub Pages JSON URL.
19. Quick Quiz
HttpClient.public folder, for example
public/data/courses.json.Final Summary
JSON processing is one of the most practical Angular skills. Once you can load JSON, display it, search it, filter it, sort it, and handle errors, you can build directories, dashboards, product lists, blogs, lesson viewers, affiliate pages, and admin panels.
| Need | Angular Tool |
|---|---|
| Display single object | Interpolation and property access |
| Display list | @for |
| Load JSON | HttpClient |
| Enable HTTP | provideHttpClient() |
| Bind search box | [(ngModel)] and FormsModule |
| Validate data shape | TypeScript interface |
| Keep code clean | Angular service |
The next natural lesson is: Angular Services and API Integration 0 to Infinity.