_TypeError (type 'Address' is not a subtype of type 'Map<String, dynamic>' in type cast)
JSON 직렬화/역직렬화 과정에서 중첩된 객체가 제대로 변환되지 않을 때 발생함.
@JsonSerializable() 어노테이션에 explicitToJson: true 옵션이 없어서, 중첩된 객체들이 JSON으로 제대로 직렬화되지 않음.
// Address 모델
()
class Address {
final String street;
final String city;
Address({required this.street, required this.city});
factory Address.fromJson(Map<String, dynamic> json) =>
_$AddressFromJson(json);
Map<String, dynamic> toJson() => _$AddressToJson(this);
}
// User 모델 (Address를 포함)
() // ❌ explicitToJson: true 없음
class User {
final String name;
final int age;
final Address address; // 중첩 객체
User({required this.name, required this.age, required this.address});
factory User.fromJson(Map<String, dynamic> json) =>
_$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
explicitToJson: true가 없을 때 생성되는 user.g.dart:
Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
'name': instance.name,
'age': instance.age,
'address': instance.address, // ❌ Address 객체가 그대로 저장됨
};
직렬화 (toJson)
final user = User(
name: '홍길동',
age: 30,
address: Address(street: '강남대로', city: '서울'),
);
final json = user.toJson();
// 결과: {'name': '홍길동', 'age': 30, 'address': Address 객체}
// ❌ address가 Map이 아니라 Address 객체 그대로
저장/전송
// 로컬 스토리지나 API에 저장
await storage.save(json);
// 실제로는 Address 객체가 직렬화되지 않은 상태로 저장됨
역직렬화 (fromJson) - 에러 발생
final savedJson = await storage.load();
final user = User.fromJson(savedJson);
// ❌ 에러 발생
// Address.fromJson()이 Map<String, dynamic>을 기대하지만
// Address 객체가 들어와서 타입 캐스팅 실패
_TypeError (type 'Address' is not a subtype of type 'Map<String, dynamic>' in type cast)
explicitToJson: true 추가수정 전:
() // ❌
class User {
final Address address;
// ...
}
수정 후:
(explicitToJson: true) // ✅
class User {
final Address address;
// ...
}
explicitToJson: true를 추가한 후 재생성된 user.g.dart:
Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
'name': instance.name,
'age': instance.age,
'address': instance.address.toJson(), // ✅ 제대로 직렬화됨
};
직렬화 (toJson)
final user = User(
name: '홍길동',
age: 30,
address: Address(street: '강남대로', city: '서울'),
);
final json = user.toJson();
// 결과: {
// 'name': '홍길동',
// 'age': 30,
// 'address': {'street': '강남대로', 'city': '서울'} // ✅ Map으로 변환됨
// }
역직렬화 (fromJson) - 정상 동작
final savedJson = await storage.load();
final user = User.fromJson(savedJson);
// ✅ 정상 동작
// address가 Map<String, dynamic>이므로 Address.fromJson()이 정상 실행됨
(explicitToJson: true) // ✅ 필수
class Order {
final List<Item> items; // 리스트 안에 중첩 객체
Order({required this.items});
// ...
}
(explicitToJson: true) // ✅ 필수
class Company {
final Address address; // 1단계 중첩
// ...
}
(explicitToJson: true) // ✅ 필수
class Employee {
final Company company; // 2단계 중첩
// ...
}
(explicitToJson: true) // ✅ 필수
class Profile {
final Address? address; // 옵셔널이어도 필요
// ...
}
중첩 객체가 있는 모든 모델에 explicitToJson: true 추가 필요:
모델 수정 후 다음 명령어 실행:
flutter pub run build_runner build --delete-conflicting-outputs
기존 데이터: 이미 잘못된 형식으로 저장된 데이터가 있다면 삭제하거나 마이그레이션 필요.
모든 중첩 레벨: 중첩이 여러 단계라면 각 단계의 모델 모두에 explicitToJson: true 추가 필요.
빌드 실행: 모델 수정 후 반드시 build_runner 실행하여 generated 파일 업데이트 필요.
@JsonSerializable()만 사용하면 중첩 객체가 JSON으로 변환되지 않음@JsonSerializable(explicitToJson: true) 추가toJson()으로 변환되어 올바르게 직렬화됨