Dart에서 JSON 데이터를 처리할 때 없는 키 값에 대한 처리는 여러 가지 방법으로 할 수 있습니다. 일반적으로는 해당 키가 없을 때 null을 반환하도록 하거나, 기본값을 제공하거나, 예외 처리를 통해 문제를 해결합니다.
다음은 MVVM 모델을 기반으로 JSON 데이터에서 없는 키 값을 처리하는 방법을 설명하고 코드를 제공해 드릴게요.
1. 솔루션 개요
JSON 데이터를 다룰 때 가장 일반적인 시나리오는 백엔드 API에서 데이터를 받아와 Dart 객체로 변환(역직렬화)하는 것입니다. 이때 API 응답이 항상 모든 키를 포함하지 않을 수 있으므로, 없는 키에 대한 안정적인 처리가 중요합니다.
여기서는 다음 단계를 통해 JSON 데이터의 없는 키 값을 처리하는 방법을 보여드릴게요.
Model 계층: JSON 데이터를 Dart 객체로 변환하는 로직을 담당합니다. 여기서는
factory생성자를 사용하여 JSON으로부터 객체를 생성할 때 없는 키를 안전하게 처리합니다.ViewModel 계층: Model에서 변환된 데이터를 UI에 표시하기 위해 준비합니다. 여기서는 Model에서 처리된 데이터를 단순히 전달합니다.
View 계층 (간단한 예시): ViewModel에서 제공된 데이터를 사용하여 UI를 구성합니다.
가정 및 제한사항:
JSON 데이터는 Dart의
Map<String, dynamic>형태로 제공된다고 가정합니다.예시에서는 간단한 사용자 데이터를 다룹니다.
네트워크 요청 부분은 생략하고, 이미
Map<String, dynamic>형태로 변환된 JSON 데이터를 사용합니다.
2. Dart 코드 및 구현 지침
아래 코드는 MVVM 패턴을 따르며, JSON 데이터에서 없는 키 값을 처리하는 다양한 방법을 보여줍니다.
2.1 Model 계층: user_model.dart
User 모델은 JSON 데이터를 Dart 객체로 변환하는 역할을 합니다. 여기서는 Map에서 값을 가져올 때 없는 키를 처리하는 세 가지 방법을 보여줍니다:
널 안정성
?연산자 및??(null-aware operator): 가장 일반적이고 권장되는 방법입니다.map['key']가null이면??뒤의 기본값을 사용합니다.containsKey()메서드:Map이 특정 키를 포함하는지 확인한 후 값을 가져옵니다.예외 처리
try-catch:Map에서 존재하지 않는 키에 접근하려 할 때 발생하는StateError를 잡아서 처리합니다. (일반적으로 JSON 파싱에서는 잘 사용되지 않지만, 다른 에러 처리 시나리오에서 유용할 수 있습니다.)
// lib/models/user_model.dart
class User {
final String? name;
final int? age;
final String? email;
final String country; // 필수 필드, 기본값 제공
User({this.name, this.age, this.email, required this.country});
// JSON Map으로부터 User 객체를 생성하는 팩토리 생성자
factory User.fromJson(Map<String, dynamic> json) {
// 1. 널 안정성 ? 연산자 및 ?? (null-aware operator) 사용: 권장
// 'name' 키가 없거나 값이 null이면 null을 할당합니다.
final String? name = json['name'] as String?;
// 'age' 키가 없거나 값이 null이면 null을 할당합니다.
final int? age = json['age'] as int?;
// 2. containsKey() 메서드 사용:
// 'email' 키가 존재하면 해당 값을 가져오고, 없으면 null을 할당합니다.
final String? email = json.containsKey('email') ? json['email'] as String? : null;
// 3. 필수 필드에 대한 처리 및 기본값 제공:
// 'country' 키가 없거나 값이 null이면 'Unknown'을 기본값으로 사용합니다.
final String country = json['country'] as String? ?? 'Unknown';
// 예외 처리 (Optional: JSON 파싱에서는 잘 사용되지 않음)
// 이 방법은 'some_required_field'가 반드시 존재해야 하고,
// 없으면 오류를 발생시키고 싶을 때 고려할 수 있습니다.
/*
String someRequiredField;
try {
someRequiredField = json['some_required_field'] as String;
} catch (e) {
print('Error parsing some_required_field: $e');
someRequiredField = 'Default Value'; // 또는 예외를 다시 던지거나 다른 처리
}
*/
return User(
name: name,
age: age,
email: email,
country: country,
);
}
@override
String toString() {
return 'User(name: $name, age: $age, email: $email, country: $country)';
}
}
설명:
name과age필드는String?및int?로 선언하여null값을 가질 수 있도록 합니다.json['name'] as String?와 같이as키워드 뒤에?를 붙여 명시적으로null값을 허용하는 형변환을 수행합니다.email필드는containsKey()를 사용하여 키 존재 여부를 확인합니다. 이는 특정 키가 존재할 때만 값을 가져오고 싶을 때 유용합니다.country필드는 필수 필드이지만, JSON에 키가 없을 경우?? 'Unknown'을 사용하여 기본값을 제공합니다. 이는 데이터의 안정성을 높이는 데 도움이 됩니다.
2.2 ViewModel 계층: user_viewmodel.dart
ViewModel은 Model의 데이터를 View에 적합한 형태로 노출합니다. 여기서는 단순히 User 객체를 View에 전달합니다. 실제 애플리케이션에서는 데이터를 가공하거나 비즈니스 로직을 포함할 수 있습니다.
// lib/viewmodels/user_viewmodel.dart
import '../models/user_model.dart';
class UserViewModel {
final User _user;
UserViewModel(this._user);
String? get userName => _user.name;
int? get userAge => _user.age;
String? get userEmail => _user.email;
String get userCountry => _user.country;
// 추가적인 비즈니스 로직이나 데이터 가공을 ViewModel에서 수행할 수 있습니다.
String get displayName {
return _user.name != null && _user.name!.isNotEmpty
? '이름: ${_user.name}'
: '이름: 미상';
}
String get displayAge {
return _user.age != null ? '나이: ${_user.age}세' : '나이: 알 수 없음';
}
String get displayEmail {
return _user.email != null && _user.email!.isNotEmpty
? '이메일: ${_user.email}'
: '이메일: 제공되지 않음';
}
String get displayCountry {
return '국가: ${_user.country}';
}
}
설명:
ViewModel은
User모델 객체를 캡슐화하고, View에서 직접 Model에 접근하는 대신 ViewModel을 통해 데이터에 접근하도록 합니다.get메서드를 통해 Model의 속성에 접근하며, 필요에 따라 데이터를 포맷하거나 변환할 수 있습니다. 예를 들어,displayName은 이름이 없을 경우 "미상"으로 표시합니다.
2.3 View 계층 (간단한 예시): main.dart
여기서는 실제 Flutter UI 대신 main 함수에서 ViewModel을 사용하여 데이터를 출력하는 방식으로 View 계층을 간단하게 시뮬레이션합니다.
// lib/main.dart
import 'dart:convert'; // JSON 문자열을 Map으로 변환하기 위해 필요
import 'package:flutter/material.dart'; // 실제 Flutter 프로젝트에서 사용될 경우
import 'models/user_model.dart';
import 'viewmodels/user_viewmodel.dart';
void main() {
// 1. 모든 키가 존재하는 JSON 데이터
String jsonString1 = '''
{
"name": "홍길동",
"age": 30,
"email": "hong.gildong@example.com",
"country": "South Korea"
}
'''
;
// 2. 일부 키가 없는 JSON 데이터
String jsonString2 = '''
{
"name": "김철수",
"age": 25
// "email"과 "country" 키가 없음
}
'''
;
// 3. 'name'도 없는 JSON 데이터
String jsonString3 = '''
{
"age": 40,
"email": "no.name@example.com",
"country": "USA"
}
'''
;
// JSON 문자열을 Map<String, dynamic>으로 변환
final Map<String, dynamic> jsonData1 = json.decode(jsonString1);
final Map<String, dynamic> jsonData2 = json.decode(jsonString2);
final Map<String, dynamic> jsonData3 = json.decode(jsonString3);
print('--- Case 1: All keys present ---');
final User user1 = User.fromJson(jsonData1);
final UserViewModel viewModel1 = UserViewModel(user1);
print(viewModel1.displayName);
print(viewModel1.displayAge);
print(viewModel1.displayEmail);
print(viewModel1.displayCountry);
print('\n--- Case 2: Missing "email" and "country" ---');
final User user2 = User.fromJson(jsonData2);
final UserViewModel viewModel2 = UserViewModel(user2);
print(viewModel2.displayName);
print(viewModel2.displayAge);
print(viewModel2.displayEmail); // "이메일: 제공되지 않음" 출력 예상
print(viewModel2.displayCountry); // "국가: Unknown" 출력 예상
print('\n--- Case 3: Missing "name" ---');
final User user3 = User.fromJson(jsonData3);
final UserViewModel viewModel3 = UserViewModel(user3);
print(viewModel3.displayName); // "이름: 미상" 출력 예상
print(viewModel3.displayAge);
print(viewModel3.displayEmail);
print(viewModel3.displayCountry);
}
설명:
main함수에서 세 가지 다른 JSON 문자열을 정의하고 있습니다. 이 문자열들은json.decode()를 통해Map<String, dynamic>형태로 변환됩니다.각
jsonData는User.fromJson()팩토리 생성자를 통해User모델 객체로 변환됩니다. 이때User모델의 로직에 따라 없는 키 값이 처리됩니다.생성된
User객체는UserViewModel의 생성자로 전달되어UserViewModel인스턴스를 생성합니다.마지막으로
UserViewModel의 게터들을 사용하여 데이터가 어떻게 처리되었는지 콘솔에 출력합니다.
구현 지침:
프로젝트 구조 설정:
새 Flutter 또는 Dart 프로젝트를 생성합니다. (예:
flutter create my_json_app)lib폴더 안에models와viewmodels폴더를 생성합니다.각 코드 파일을 해당 폴더에 저장합니다:
lib/models/user_model.dartlib/viewmodels/user_viewmodel.dartlib/main.dart
의존성 추가 (선택 사항):
이 예시에서는 별도의 패키지가 필요하지 않습니다. Dart의 내장
dart:convert라이브러리로 충분합니다.만약 더 복잡한 JSON 직렬화/역직렬화를 위해
json_serializable과 같은 패키지를 사용하고 싶다면,pubspec.yaml파일에 추가해야 합니다.
코드 실행:
터미널에서 프로젝트 루트 디렉토리로 이동합니다.
다음 명령을 실행하여 코드를 실행합니다:
Bashdart lib/main.dart콘솔에서 출력되는 결과를 확인하여 없는 키 값이 어떻게 처리되는지 볼 수 있습니다.
이 예시를 통해 Dart에서 JSON 데이터의 없는 키 값을 안전하게 처리할 수 있습니다.
0 댓글