Flutter - 클래스 모델링 - Json 데이터를 클래스 멤버 변수에 적재하기

 

HTTP 요청을 통해(API) 데이터를 받을 때 항상 데이터 타입과 파싱에 대한 어려움을 겪곤 합니다.

여러 개의 리스트로 구성된 JSON 데이터를 받을 땐 어떻게 해야 할지 항상 고민하는데,

이 글이 도움이 되면 좋겠기에 작성합니다.


Preview

  • API 응답 결과의 두번째 인덱스의 제목 가져오기
// response : HTTP GET 요청의 응답 결과로 가정
print('\n ***** GET Response : \n$response');
print('\n ***** 두번째 인덱스의 제목 : \n ***** ${dataResList[1].title}');


// flutter: 
// ***** GET Response : 
// {result: [{content: hello world, id: 1, name: Eunbyeol, title: Hello!}, {content: content, id: 2, name: test, title: title}]}
// flutter: 
// ***** 두번째 인덱스의 제목 : 
// ***** title

예시

  • HTTP GET 요청으로 응답받은 JSON 값
result :
[
    {
    'id' : 1,
    'name' : 'Eunbyeol',
    'title' : 'Hello!',
    'content' : 'hello world'
    },
    {
    'id' : 2,
    'name' : 'test',
    'title' : 'title',
    'content' : 'content'
    }
]

클래스 정의

  • 클래스와 멤버 변수 선언
class DataResources {
  int id;
  String name;
  String title;
  String content;
}

 

  • 생성자 초깃값 설정
    • required this.변수명
  DataResources({
    required this.id,
    required this.name,
    required this.title,
    required this.content,
  });

 

  • Json 타입의 값을 저장하기 위한 팩토리 생성자
  • 팩토리 생성자란?
    • 새 인스턴스를 직접 생성하지 않는 특별한 유형의 생성자
    • 개체 생성 프로세스를 사용자가 지정하는 방법을 제공
    • fromJson 메서드를 이용하여 JSON 개체를 클래스의 멤버 변수에 할당
  factory DataResources.fromJson(Map<String, dynamic> data) {
    return DataResources(
      id: data['id'],
      name: data['name'],
      title: data['title'],
      content: data['content'],
    );
  }

 

  • Json 타입의 모든 데이터를 리스트로 저장
    • 방법1 : 클래스 모델링 시 파라미터를 입력하면 자동으로 팩토리 생성자를 통해 멤버 변수에 할당
    • 방법2 : API의 응답 결과를 직접 map 함수를 통해 팩토리 생성자로 멤버 변수에 할당
/* 방법1 */
// fromJsonList 함수 정의
static List<DataResources> fromJsonList(Map<String, dynamic> data) {
  // API 응답 결과를 리스트로 저장
  final List<dynamic> resultList = data['result'];
  // 리스트의 값들을 맵 함수를 통해 팩토리 생성자의 멤버 변수에 할당
  return resultList.map((data) => DataResources.fromJson(data)).toList();
}
  
// 사용
// response : HTTP 요청 결과의 변수로 가정
final List<DataResources> dataResList =
          DataResources.fromJsonList(response);

// 데이터 출력 : 변수[인덱스].멤버변수명
print('GET Result dataResList : ${dataResList[0].name}'); // GET Result dataResList : Eunbyeol

 

/* 방법2 */
// response : HTTP 요청 결과의 변수로 가정
final List<DataResources> dataResList2 = List<DataResources>.from(
    response['result'].map((data) => DataResources.fromJson(data)));
    
// 데이터 출력 : 변수[인덱스].멤버변수명
print('GET Result dataResList2 : ${dataResList[1].name}'); // GET Result dataResList2 : test

사용 예시

  • 예시에서 사용된 라이브러리
    • dart:io
    • dart:convert
  • HTTP 요청 방법 : HttpClient 사용하여 GET 메소드 호출

main.dart

  • HTTP GET 요청을 하고 응답 결과 저장
import 'dart:convert';
import 'dart:io';
import 'package:flutter_api_http_test/apiRes.dart';
import 'package:flutter/material.dart';

void main() {
  getUseHttpClient();
}

/* GET Method : dart.io 라이브러리의 HttpClient 사용 */
void getUseHttpClient() async {
  // 클라이언트 인스턴스 생성
  final client = HttpClient();
  try {
    // API 요청
    final request = await client.getUrl(Uri.parse('http://127.0.0.1:5000/'));
    // 요청 종료
    final response = await request.close();

    // 요청 성공일 경우
    if (response.statusCode == HttpStatus.ok) {
      // 응답 결과 저장
      final responseBody = await response.transform(utf8.decoder).join();
      final parseResponse = json.decode(responseBody);
      print('\n ***** GET Response : $parseResponse');
      //  ***** GET Response :
      //  {result: [{content: hello world, id: 1, name: Eunbyeol, title: Hello!}, {content: content, id: 2, name: test, title: title}]}

      // 응답 결과를 리스트 형태로 저장 : 정의한 함수를 호출하여 변환
      final List<DataResources> dataResList =
          DataResources.fromJsonList(parseResponse);
      print(
          '\n ***** Result dataResList Value(name) : \n ***** ${dataResList[0].name}');
          //  ***** Result dataResList Value(name) : 
          //  ***** Eunbyeol

      // 응답 결과를 리스트의 형태로 저장 : 직접 명시하여 변환
      final List<DataResources> dataResList2 = List<DataResources>.from(
          parseResponse['result'].map((data) => DataResources.fromJson(data)));
      print(
          '\n ***** Result dataResList2 Value(title) : \n ***** ${dataResList2[0].title}');
          //  ***** Result dataResList2 Value(title) : 
          //  ***** Hello!

      // 응답 결과의 하나의 리스트를 클래스 멤버 변수에 저장
      final dataRes = DataResources.fromJson(parseResponse['result'][1]);
      print('\n ***** Result dataRes Value(name) : \n ***** ${dataRes.name}');
      //  ***** Result dataRes Value(name) : 
      //  ***** test
      

    }
    // 요청 실패 일 경우
    else {
      print('Request failed with status : ${response.statusCode}');
    }
  }
  // 클라이언트 접속 오류일 경우
  catch (e) {
    print('Error : $e');
  } finally {
    // 클라이언트 연결 정료
    client.close();
  }
}

apiRes.dart

  • API 요청의 응답 결과를 저장하기 위한 클래스 모델링 코드
class DataResources {
  int id;
  String name;
  String title;
  String content;

  DataResources({
    required this.id,
    required this.name,
    required this.title,
    required this.content,
  });

  factory DataResources.fromJson(Map<String, dynamic> data) {
    return DataResources(
      id: data['id'],
      name: data['name'],
      title: data['title'],
      content: data['content'],
    );
  }

  static List<DataResources> fromJsonList(Map<String, dynamic> data) {
    final List<dynamic> resultList = data['result'];
    return resultList.map((data) => DataResources.fromJson(data)).toList();
  }
}

실행