Model_JSON 직렬화

jju·2023년 12월 5일
0

flutter_json

목록 보기
1/1

직렬화는 데이터를 효과적으로 저장하고 전송하는 데 필수적인 역할을 하며, 복잡한 데이터 구조를 간단한 형태로 변환하는 데에도 중요합니다.

  • 데이터 전송과 저장의 용이성 , 데이터 통합 및 교환 용이성

Json_기본

import 'dart:convert';

// api에서 내려오는 데이터를 가정하에 jsonStr에 데이터를 기입하였습니다.
void main() {
  // 1. JSON 문자열 정의
  String jsonStr = '{"name": "John", "age": 30, "email": "john@example.com"}';

  // 2. JSON Decode: JSON 문자열을 Map 구조로 변환, decode 변환 : json.decode 메소드를 사용하여 Dart의 Map<String, dynamic> 구조로 변환
  Map<String, dynamic> userMap = json.decode(jsonStr);

  // 3. fromJson 메소드: Map 구조를 사용하여 User 객체 생성
  User user = User.fromJson(userMap);

  // User 객체 사용 예시
  print('Name: ${user.name}');
  print('Age: ${user.age}');
  print('Email: ${user.email}');
}

// 📎 아래 클래스는 보통 페이지를 별로도 구현합니다.
class User {
  String name;
  int age;
  String email;

  User({required this.name, required this.age, required this.email});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'],
      age: json['age'],
      email: json['email'],
    );
  }
}

//출력
I/flutter (13835): Name: John
I/flutter (13835): Age: 30
I/flutter (13835): Email: john@example.com

Json_기본(api)

  • api 추가
import 'package:http/http.dart' as http;
import 'dart:convert';

// User 클래스 정의
class User {
  String name;
  int age;
  String email;

  User({this.name, this.age, this.email});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'],
      age: json['age'],
      email: json['email'],
    );
  }
}

void fetchUserData() async {
  final response = await http.get(Uri.parse('https://example.com/user'));

  if (response.statusCode == 200) {
    // 서버로부터 받은 JSON 문자열
    String jsonStr = response.body;

    // JSON 문자열을 Dart 객체로 변환
    Map<String, dynamic> userMap = json.decode(jsonStr);
    User user = User.fromJson(userMap);

    // User 객체의 데이터 출력
    print('User Name: ${user.name}');
    print('User Age: ${user.age}');
    print('User Email: ${user.email}');
  } else {
    // 서버에서 에러 응답을 받은 경우 처리
    print('Failed to load user data');
    throw Exception('Failed to load user data');
  }
}

void main() {
  fetchUserData();
}

Json_json_serialized

Json_json_serialized을 이용하기 위해서는 두개의 패키지를 설치해야 합니다. (pubdev)
1. json_annotation: ^4.8.1 - dependencies에 패키지를 설치합니다.
2.json_serializable: ^6.7.1 - dev_dependencies에 설치합니다. 빌드 할때 한번만 이용하기 때문

  • 가장 큰 이유는 반복적이고 코드를 작성할때 실수가 일어 날 수 있기에 이를 방지하기 위해 쓰인다.
  • 프로젝트가 커짐에 따라 사용하기에 용이,유지보수 용이, 타입 안정성, 오류를 감소, 코드간소화
  • 코드 및 part 부분이 설정이 완료되면 "flutter pub run build_runner build" 터미널에 입력합니다.
  • 위 코드가 터미널에서 작동하지 않을 경우 build_runner 패키지가 설치 되었는지 확인 후 안되어 있을경우 설치해야 합니다.
import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart'; // 자동 생성될 파일

@JsonSerializable()
class User {
  String name;
  int age;
  String email;

  User({this.name, this.age, this.email});

  // json_serializable에서 제공하는 메소드
  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'user.dart'; // User 클래스를 정의한 파일

void fetchUserData() async {
  final response = await http.get(Uri.parse('https://example.com/user'));

  if (response.statusCode == 200) {
    // 서버로부터 받은 JSON 문자열
    String jsonStr = response.body;

    // JSON 문자열을 Dart 객체로 변환
    Map<String, dynamic> userMap = json.decode(jsonStr);
    User user = User.fromJson(userMap);

    // User 객체의 데이터 출력
    print('User Name: ${user.name}');
    print('User Age: ${user.age}');
    print('User Email: ${user.email}');
  } else {
    // 서버에서 에러 응답을 받은 경우 처리
    print('Failed to load user data');
  }
}

받아오는 데이터를 다른 곳에서는 다른 변수값을 설정하고 싶을경우에는 @jsonKey를 이용해야합니다.
받아오는 데이터는 priviewURL 이지만 jsonKey를 통해 custom하여 내부에서는 preiewUrl로 쓰일 수 있습니다.

@JsonKey(name: 'previewURL')
  String previewUrl;
  • 이후에 equatable 패키지를 통해 불변객체를 만들 수 있는 방법도 알아보자
    -가능하면 변수보다는 상수를 쓰는게 좋고, 변하는 값보다는 불변객체를 만드는게 좋다.

freezed

  • freezed를 이용해서 json 직렬화도 가능합니다.

예) JsonSerializable 과 freezed의 차이점을 보여주는 코드이고 이용하기 위해서는 JsonSerializable을 삭제합니다.

import 'package:json_annotation/json_annotation.dart';

part 'photo.g.dart';

@JsonSerializable()
class Photo {
  int id;
  String tags;
  @JsonKey(name: 'previewURL')
  String previewUrl;

  Photo({required this.id, required this.tags, required this.previewUrl});

  factory Photo.fromJson(Map<String,dynamic> json) => _$PhotoFromJson(json);

  Map<String, dynamic> toJson() => _$PhotoToJson(this);
}

@freezed
class Photo with _$Photo {
  factory Photo({
    required int id,
    required String tags,
    required @JsonKey(name: 'previewURL') String previewUrl,
}) = _Photo
  factory Photo.fromJson(Map<String, dynamic> json) => _$PhotoFromJson(json);
}

freezed 적용 (build runner 는 JsonSerializable과 동일합니다.)

import 'dart:async';

import 'package:image_search/data/api.dart';
import 'package:image_search/model/photo.dart';

class HomeViewModel {
  final  PixabayApi api;

  final _photoScreamController = StreamController<List<Photo>>()..add([]); //기존 photo를 담아주는 데이터를 없에고 controller로 대체합니다. 최초에는 데이터가 없으므로 circulr가 보이는데 add를 추가하여 빈 값을 출력하게 합니다.
  Stream<List<Photo>> get photoStream => _photoScreamController.stream;

  HomeViewModel(this.api);
  Future<void> fetch(String query) async {
    final result = await api.fetch(query);
    _photoScreamController.add(result);
  }
}
profile
한결

0개의 댓글