Dependency
https://pub.dev/packages/dart_json_mapper λ₯Ό μ¬μ©νλ€
flutter pub add dart_json_mapper
Bash
볡μ¬
pubspec.yaml νμΌμ build_runnerλ₯Ό μΆκ°ν©λλ€.
...
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
...
dart_json_mapper: ^2.1.17
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: πππππππππ μ΄ λΆλΆμ΄ μΆκ°λμ΄μΌ ν©λλ€.
YAML
볡μ¬
κ·Έλ¦¬κ³ `flutter pub get` λͺ
λ Ήμ΄λ‘ dependency μ€μΉλ₯Ό μ§νν©λλ€.
build.yaml μμ±
flutter root λλ ν 리μ build.yaml νμΌμ μμ±νκ³ μλ λ΄μ©μ λΆμ¬λ£λλ€.
targets:
$default:
builders:
dart_json_mapper:
generate_for:
# here should be listed entry point files having 'void main()' function
- lib/main.dart ππππππ main() ν¨μκ° μλ νμΌ pathλ₯Ό μ ννκ² μ μ΄μΌ ν©λλ€
# This part is needed to tell original reflectable builder to stay away
# it overrides default options for reflectable builder to an **empty** set of files
reflectable:
generate_for:
- no/files
YAML
볡μ¬
κ·Έλ¦¬κ³ μλμ λͺ
λ Ήμ΄λ₯Ό μ
λ ₯νλ€
flutter pub run build_runner watch --delete-conflicting-outputs
Bash
볡μ¬
μ λͺ
λ Ήμ΄λ flutter νλ‘μ νΈλ₯Ό μ μ₯νλ©΄ μ€νλλ©°, *.dart νμΌμ νμ ν @jsonSerializable μ΄λ
Έν
μ΄μ
μ΄ λΆμ ν΄λμ€λ€μ μ°Ύμμ main.mapper.g.dart νμΌμ μμ±ν΄μ€λ€. μ±
μ μμ μ½λ© μ€λΉλ₯Ό λ§μΉκ³ μ μ€ν¬λ¦½νΈλ₯Ό μ€νν΄μ£Όμ.
fyi) reflectionμ΄ κ° μΈμ΄μμ κ°μ₯ μ μ©νκ² μ¬μ©λλ λΆλΆμ jsonμ object λ‘ mapping ν λ μ¬μ©λ©λλ€. κ·Έλ¦¬κ³ dart λ reflectionμ΄ μ§μλμ§ μμ΅λλ€. μλλλ° μ μ¬κΈ°μ μ΄μΌκΈ° νλλ?
μλλ©΄ λκ² νλκ² μμ§λμ΄μ£ .. @jsonSerializaiton μ΄λΌλ μ΄λ
Έν
μ΄μ
μ λ§λ€κ³ prebuild μμ μ μ€ν¬λ¦½νΈλ₯Ό ν΅ν΄μ reflection μ²λΌ μ¬μ©ν μ μλ νλ‘νΌν°λ€μ κ°μ μ£Όμ
νλ λ°©μμΌλ‘ reflection μ νλ΄λμ΅λλ€.
μμ
μ΄ μλ£λλ€. ν°λ―Έλ νλ‘μΈμ€λ μλ μ’
λ£λμ§ μμΌλ [INFO] Succeeded after 15.6s with 1 outputs (1 actions) λ¬Έκ΅¬κ° λμ€λ©΄ Ctrl+C λ‘ νλ‘μΈμ€λ₯Ό μ’
λ£μν¨λ€
Android Studio λ‘ λμμμ Directoryλ₯Ό 보면 main.mapper.g.dart νμΌμ΄ μμ±λ κ²μ λ³Ό μ μλ€.
κ·Έ ν main() ν¨μκ° μλ main.dart νμΌμμ initializeJsonMapper() ν¨μλ₯Ό μ€νν΄μ£Όλ μ½λλ₯Ό μΆκ°ν©λλ€.
void main() async {
Constants.setEnvironment(Environment.STAGING);
WidgetsFlutterBinding.ensureInitialized();
initializeJsonMapper(); ππππ
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(App());
}
Dart
볡μ¬
Trouble Shooting
1.
_memberSymbolMap is not assined
~.mapper.g.dart νμΌμ μμ±λμμ§λ§ λ΄λΆ _memberSymbolMap, _data λ³μκ° μ λλ‘ μ μΈλμ§ μμ μ»΄νμΌ μλ¬κ° λ°μνκ³ μ΄λ₯Ό ν΄κ²°νμ΅λλ€.
void main() {} ν¨μκ° μλ νμΌμ
import 'package:reflectable/reflectable.dart';
μ μ½λ μΆκ°κ° νμν©λλ€. μ¬μ©νμ§ μλ importμ§λ§
flutter pub run build_runner watch --delete-conflicting-outputs
Bash
볡μ¬
μ λͺ
λ Ήμ΄κ° μ μμ μΌλ‘ μνλκΈ° μν΄μλ μ import ꡬ문μ λ£μ΄μ€μΌ μ μμ μΌλ‘ λμν¨μ νμΈνμ΅λλ€.
^ μ μ΄μλ json_dart_mapper μ΅μ λ²μ μμ μμ λμμ΅λλ€.
2.
μ μ λκ° Unhandled Exception: Bad state: Reflectable has not been initialized. μ΄μ
void main() ν¨μκ° μλ κ³³μ @JsonSerializable()μ μ¬μ©νλ νμΌμ μμμ
μΌλ‘ import ν΄μ€μΌν©λλ€.
κ·Έ ν ν°λ―Έλμμ
flutter pub run build_runner build --delete-conflicting-outputs
Bash
볡μ¬
λͺ
λ Ήμ΄λ₯Ό μ€ννκ³ ~.mapper.g.dart νμΌμ 보면 νμΌ λ΄μ©(?) μ΄ λ§μμ§ κ²μ νμΈν μ μκ³ ,
μ΄ μνμμ flutter μ± μ€νμ μ μ μνλ¨μ νμΈν μ μμ΅λλ€.
API Response μ€λ¬΄ μμ
κ°μΈ νλ‘μ νΈμμ μ¬μ©νλ API Response Format μ μκ°νμ μμ΅λλ€. Flutter μμλ λΉμ°ν λμΌν formatμ λ°λ₯Ό μμ μ
λλ€.
ResponseFormat.dart
import 'package:dart_json_mapper/dart_json_mapper.dart';
class ResponseJSON<T> {
final ResponseHeader header;
final T data;
ResponseJSON({
this.header,
this.data
});
factory ResponseJSON.fromJson(Map<String, dynamic> json, Function(Map<String, dynamic>) fromJson) {
return ResponseJSON(
header: ResponseHeader.fromJson(json['header']),
data: fromJson(json['data']),
);
}
} // Single Object νμ
μ Responseλ₯Ό νμ±νκΈ° μν Response Format
class ResponseListJSON<T> {
final ResponseHeader header;
final List<T> data;
ResponseListJSON({
this.header,
this.data
});
factory ResponseListJSON.fromJson(Map<String, dynamic> json, Function(Map<String, dynamic>) fromJson) {
List<T> list = List<T>.from(json['data'].map((model) => fromJson(model)));
return ResponseListJSON(
header: ResponseHeader.fromJson(json['header']),
data: list,
);
}
} // List νμ
μ Responseλ₯Ό νμ±νκΈ° μν Response Format
Dart
볡μ¬
Promotion.dart
import 'package:dart_json_mapper/dart_json_mapper.dart';
class Promotion {
final String brandName;
final String brandLogoURL;
final int boltPrice;
final int boltEffectiveness;
final int discountRate;
final int priceMax;
final int discountMax;
final String description;
Promotion({
this.brandName,
this.brandLogoURL,
this.boltPrice,
this.boltEffectiveness,
this.discountRate,
this.priceMax,
this.discountMax,
this.description
});
factory Promotion.fromJson(Map<String, dynamic> json) {
return Promotion(
brandName: json['brandName'],
brandLogoURL: json["brandLogoURL"],
boltPrice: json["boltPrice"],
boltEffectiveness: json['boltEffectiveness'],
discountRate: json['discountRate'],
priceMax: json['priceMax'],
discountMax: json['discountMax'],
description: json['description'],
);
}
}
Dart
볡μ¬
μ μ½λλ₯Ό λͺ¨λ μμ± ν ν μλ 2κ° μ€ 1κ°λ₯Ό μ¬μ©νλ©΄ λ©λλ€.
flutter pub run build_runner watch --delete-conflicting-outputs
Dart
볡μ¬
νμΌ λ³κ²½μ μλμΌλ‘ main.mapper.g.dart νμΌμ μ
λ°μ΄νΈν©λλ€.
flutter pub run build_runner build --delete-conflicting-outputs
Dart
볡μ¬
μλμΌλ‘ μ
λ°μ΄νΈ ν©λλ€.
PromotionProvider.dart
import 'dart:convert';
import 'package:chai_booster/Entity/Promotion.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class PromotionProvider with ChangeNotifier {
List<Promotion> promotion = [];
final client = http.Client();
// Action
void fetchPromotions() async {
final response = await client.get(Uri.parse('http://localhost:5001/chai-booster/asia-northeast3/api/booster/v1/promotions'));
final data = ResponseListJSON<Promotion>.fromJson(json.decode(response.body), (data) => Promotion.fromJson(data)).data;
promotion = data;
notifyListeners();
}
}
Dart
볡μ¬
^ μ μ½λμμ λμ¬κ²¨λ΄μΌν λΆλΆμ 14λ²μ§Έ λΌμΈ
final data = ResponseListJSON<Promotion>.fromJson(json.decode(response.body), (data) => Promotion.fromJson(data)).data;
Dart
볡μ¬
μμ κ°μ΄ μ¬μ©νλ©΄ data μ Promotion λ°°μ΄μ΄ κΉλνκ² λ¨μ΄μ§λ€.
λ.