이번에 도로명 주소를 검색하는 API 기능을 구현하겠습니다.
화면 레이아웃은 다음에 구현 예정입니다.
개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1
api 서버는 "https://www.juso.go.kr/openIndexPage.do" 사이트를 이용했습니다.
API 키는 여기서("https://www.juso.go.kr/addrlink/openApi/apiReqst.do") 신청하면 됩니다.
개발용 키는 본인 인증이 필요없으므로 필수정보를 대략 입력해도 발급 가능합니다.
open API 를 이용하기 위해서 추가한 패키지는
dio: ^4.0.6
./src/models/address_model.dart - 모델링 파일 추가
모델링을 만들때 사용한 데이터는 아래 더보기를 클릭하면 볼수 있다.
/*
{
"results": {
"common": {
"totalCount": "62",
"currentPage": "1",
"countPerPage": "2",
"errorCode": "0",
"errorMessage": "정상"
},
"juso":[
{
"roadAddr": "서울특별시 용산구 원효로71길 6(원효로2가)",
"roadAddrPart1": "서울특별시 용산구 원효로71길 6",
"roadAddrPart2": "(원효로2가)",
"jibunAddr": "서울특별시 용산구 원효로2가 1-25",
"engAddr": "6 Wonhyo-ro 71-gil, Yongsan-gu, Seoul",
"zipNo": "04364",
"admCd": "1117011300",
"rnMgtSn": "111704106256",
"bdMgtSn": "1117011300100010025019119",
"detBdNmList": "",
"bdNm": "",
"bdKdcd": "0",
"siNm": "서울특별시",
"sggNm": "용산구",
"emdNm": "원효로2가",
"liNm": "",
"rn": "원효로71길",
"udrtYn": "0",
"buldMnnm": "6",
"buldSlno": "0",
"mtYn": "0",
"lnbrMnnm": "1",
"lnbrSlno": "25",
"emdNo": "01",
"hstryYn": "0",
"relJibun": "",
"hemdNm": "서울특별시 용산구 원효로제1동"
},
{
"roadAddr": "서울특별시 용산구 원효로71길 7(원효로2가)",
"roadAddrPart1": "서울특별시 용산구 원효로71길 7",
"roadAddrPart2": "(원효로2가)",
"jibunAddr": "서울특별시 용산구 원효로2가 8-15",
"engAddr": "7 Wonhyo-ro 71-gil, Yongsan-gu, Seoul",
"zipNo": "04364",
"admCd": "1117011300",
"rnMgtSn": "111704106256",
"bdMgtSn": "1117011300100080015019071",
"detBdNmList": "",
"bdNm": "",
"bdKdcd": "0",
"siNm": "서울특별시",
"sggNm": "용산구",
"emdNm": "원효로2가",
"liNm": "",
"rn": "원효로71길",
"udrtYn": "0",
"buldMnnm": "7",
"buldSlno": "0",
"mtYn": "0",
"lnbrMnnm": "8",
"lnbrSlno": "15",
"emdNo": "01",
"hstryYn": "0",
"relJibun": "",
"hemdNm": "서울특별시 용산구 원효로제1동"
}
]
}
}
*/
그리고 모델링을 도와주는 사이트 및 사용방법은 아래 링크를 참고하기 바랍니다.
2022.06.30 - [Flutter/04 Widgets] - [Flutter] Widgets - Google map 2
import 'dart:convert';
AddressModel addressFromJson(String str) =>
AddressModel.fromJson(json.decode(str));
String addressToJson(AddressModel data) => json.encode(data.toJson());
class AddressModel {
Results results;
AddressModel({
required this.results,
});
factory AddressModel.fromJson(Map<String, dynamic> json) => AddressModel(
results: Results.fromJson(json["results"]),
);
Map<String, dynamic> toJson() => {
"results": results.toJson(),
};
}
class Results {
Common common;
List<Juso> juso;
Results({
required this.common,
required this.juso,
});
factory Results.fromJson(Map<String, dynamic> json) => Results(
common: Common.fromJson(json["common"]),
juso: List<Juso>.from(json["juso"].map((x) => Juso.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"common": common.toJson(),
"juso": List<dynamic>.from(juso.map((x) => x.toJson())),
};
}
class Common {
String totalCount;
String currentPage;
String countPerPage;
String errorCode;
String errorMessage;
Common({
required this.totalCount,
required this.currentPage,
required this.countPerPage,
required this.errorCode,
required this.errorMessage,
});
factory Common.fromJson(Map<String, dynamic> json) => Common(
totalCount: json["totalCount"] ?? '',
currentPage: json["currentPage"] ?? '',
countPerPage: json["countPerPage"] ?? '',
errorCode: json["errorCode"] ?? '',
errorMessage: json["errorMessage"] ?? '',
);
Map<String, dynamic> toJson() => {
"totalCount": totalCount,
"currentPage": currentPage,
"countPerPage": countPerPage,
"errorCode": errorCode,
"errorMessage": errorMessage,
};
@override
String toString() {
return 'Common{totalCount: $totalCount, currentPage: $currentPage, countPerPage: $countPerPage, errorCode: $errorCode, errorMessage: $errorMessage}';
}
}
class Juso {
String roadAddr;
String roadAddrPart1;
String roadAddrPart2;
String jibunAddr;
String engAddr;
String zipNo;
String admCd;
String rnMgtSn;
String bdMgtSn;
String detBdNmList;
String bdNm;
String bdKdcd;
String siNm;
String sggNm;
String emdNm;
String liNm;
String rn;
String udrtYn;
String buldMnnm;
String buldSlno;
String mtYn;
String lnbrMnnm;
String lnbrSlno;
String emdNo;
String hstryYn;
String relJibun;
String hemdNm;
Juso({
required this.roadAddr,
required this.roadAddrPart1,
required this.roadAddrPart2,
required this.jibunAddr,
required this.engAddr,
required this.zipNo,
required this.admCd,
required this.rnMgtSn,
required this.bdMgtSn,
required this.detBdNmList,
required this.bdNm,
required this.bdKdcd,
required this.siNm,
required this.sggNm,
required this.emdNm,
required this.liNm,
required this.rn,
required this.udrtYn,
required this.buldMnnm,
required this.buldSlno,
required this.mtYn,
required this.lnbrMnnm,
required this.lnbrSlno,
required this.emdNo,
required this.hstryYn,
required this.relJibun,
required this.hemdNm,
});
factory Juso.fromJson(Map<String, dynamic> json) => Juso(
roadAddr: json["roadAddr"] ?? '',
roadAddrPart1: json["roadAddrPart1"] ?? '',
roadAddrPart2: json["roadAddrPart2"] ?? '',
jibunAddr: json["jibunAddr"] ?? '',
engAddr: json["engAddr"] ?? '',
zipNo: json["zipNo"] ?? '',
admCd: json["admCd"] ?? '',
rnMgtSn: json["rnMgtSn"] ?? '',
bdMgtSn: json["bdMgtSn"] ?? '',
detBdNmList: json["detBdNmList"] ?? '',
bdNm: json["bdNm"] ?? '',
bdKdcd: json["bdKdcd"] ?? '',
siNm: json["siNm"] ?? '',
sggNm: json["sggNm"] ?? '',
emdNm: json["emdNm"] ?? '',
liNm: json["liNm"] ?? '',
rn: json["rn"] ?? '',
udrtYn: json["udrtYn"] ?? '',
buldMnnm: json["buldMnnm"] ?? '',
buldSlno: json["buldSlno"] ?? '',
mtYn: json["mtYn"] ?? '',
lnbrMnnm: json["lnbrMnnm"] ?? '',
lnbrSlno: json["lnbrSlno"] ?? '',
emdNo: json["emdNo"] ?? '',
hstryYn: json["hstryYn"] ?? '',
relJibun: json["relJibun"] ?? '',
hemdNm: json["hemdNm"] ?? '',
);
Map<String, dynamic> toJson() => {
"roadAddr": roadAddr,
"roadAddrPart1": roadAddrPart1,
"roadAddrPart2": roadAddrPart2,
"jibunAddr": jibunAddr,
"engAddr": engAddr,
"zipNo": zipNo,
"admCd": admCd,
"rnMgtSn": rnMgtSn,
"bdMgtSn": bdMgtSn,
"detBdNmList": detBdNmList,
"bdNm": bdNm,
"bdKdcd": bdKdcd,
"siNm": siNm,
"sggNm": sggNm,
"emdNm": emdNm,
"liNm": liNm,
"rn": rn,
"udrtYn": udrtYn,
"buldMnnm": buldMnnm,
"buldSlno": buldSlno,
"mtYn": mtYn,
"lnbrMnnm": lnbrMnnm,
"lnbrSlno": lnbrSlno,
"emdNo": emdNo,
"hstryYn": hstryYn,
"relJibun": relJibun,
"hemdNm": hemdNm,
};
}
./src/screens/start/address_service.dart - api 호출 및 데이터 변환
apiKey 들은 별도의 파일로 관리하고 깃헙에 올라가지 않게 예외처리를 해서 유출을 방지한다.
import 'package:apple_market3/src/Models/address_model.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import '../../../keys.dart';
import '../../utils/logger.dart';
class AddressService {
// string -> json(이부분은 fltter에서 자동처리함) -> object
void searchAddressByStr(String text) async {
final formData = {
'confmKey': jusoKey, // <--- 개발 테스트용 apiKey
'currentPage': '1',
'countPerPage': '100',
'keyword': text,
'resultType': 'json',
};
var resp = await Dio()
.get('http://www.juso.go.kr/addrlink/addrLinkApi.do',
queryParameters: formData)
.catchError((e) {
logger.e(e.message);
});
AddressModel addressModel = AddressModel.fromJson(resp.data);
debugPrint(addressModel.results.common.toJson().toString());
debugPrint(addressModel.results.juso.length.toString());
debugPrint(addressModel.results.juso[0].toJson().toString());
logger.d(resp.data is Map);
}
}
./src/screens/start/address_page.dart - 함수 호출 추가
TextButton.icon(
label: Text(
_isGettingLocation ? '위치 찾는중 ~~' : '현재위치 찾기',
style: Theme.of(context).textTheme.button,
),
onPressed: () {
final text = _addressController.text;
if(text.isNotEmpty){
debugPrint('address page >> clicked ~~ $text');
FocusScope.of(context).unfocus();
// 함수 호출
AddressService().searchAddressByStr(text);
}
}, //myLocation,
icon: _isGettingLocation
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(color: Colors.white))
: const Icon(CupertinoIcons.compass,
color: Colors.white, size: 20),
),
'Flutter > 12 Clone 'Used Goods app'' 카테고리의 다른 글
[Flutter] Clone - 당근마켓12(geocoding & reverse geocoding) (0) | 2022.07.24 |
---|---|
[Flutter] Clone - 당근마켓11(Address - ListView) (0) | 2022.07.22 |
[Flutter] Clone - 당근마켓9(logout) (0) | 2022.07.21 |
[Flutter] Clone - 당근마켓8(authorization-login) (0) | 2022.07.21 |
[Flutter] Clone - 당근마켓7(PageView - auth page) (0) | 2022.07.20 |