새로운 강의는 이제 https://memi.dev 에서 진행합니다.
memi가 Vue & Firebase로 직접 만든 새로운 사이트를 소개합니다.

바로가기


Flutter와 Firebase로 Android iOS 둘 다 만들기 12 JSON 데이터 예외 처리하기

1 분 소요

플러터로 일반적이지 않은 JSON 데이터를 처리해봅니다.

개요

지난 강의에서 일반적인 문자열과 숫자는 간단히 처리했지만, 날짜형과 지정 변수(_로 시작되는..)는 처리가 안됩니다.

기본 JsonSerializable 방법으로 처리할 수 없을 때 커스터마이징할 수 있는 방법을 다룹니다.

키 사용자화

언더바로 시작하는 변수(_id, _abcd 처럼..)는 다트라는 언어에서는 private, 즉 해당 클래스에서만 사용하겠다고 하는 예약되어 있어서 지난번 처럼 사용이 안됩니다.

몽고디비(mongoDB)를 다뤄보신 분들은 아시겠지만.. _id는 기본 키로 정말 꼭 필요한 구분 데이터입니다.

models/user.dart

@JsonSerializable()
class User {
  //..
  String _id; // 이렇게 사용할 수 없음..

해결은 간단합니다.

models/user.dart

@JsonSerializable()
class User {
  //..
  @JsonKey(name: '_id')
  String id;

키이름을 다르게 지정하고 선언부 위에 실제 키이름을 적어두면 끝납니다.

값 사용자화

문자, 숫자 같은 것이 아닌 DateTime 같은 다른 형식으로 변환할 때

기존 함수(fromJson, toJson)에 예외를 추가해서 사용할 수 있습니다.

models/user.dart

@JsonSerializable()
class User {
  //..
  @JsonKey(fromJson: _fromJson, toJson: _toJson)
  DateTime time;
}

factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);

static DateTime _fromJson(String s) => DateTime.parse(s);
static String _toJson(DateTime t) => t.toIso8601String();

time 변수만 다른 함수로 변환하도록 만들었습니다.

서버측 코드 테스트

.get('/', (ctx, next) => {
  const user = {
    email: 'abcd@aaa.aaa',
    name: 'abcdefg',
    address: {
      city: 'seoul',
      no: 33
    },
    friends: ['abc', 'deef', 'eewg'],
    age: 33,
    parents: ['xxx', 'e', 'eewg'],
    _id: 'abcd',
    time: new Date().toISOString()
  }
  ctx.body = user
})

잘 변환 됨을 알 수 있습니다.

toString 만들기

클래스형 변수를 콘솔에 찍어보면 항상 뭔가 찍히는데 기본으로 toString()이 들어가 있습니다.

확인이 어려운 경우가 많습니다.(instance of.. 어쩌구..) 그래서 사용자화 하는 것이 편합니다.

models/user.dart

@override
String toString() {
  return '$email, $name, ${address.city}, ${address.no} $time';
}

post로 전송해보기

지난번과 반대로 클래스 변수를 문자로 변경해야합니다.

클래스 만들기

User user = User('e', 'n', Address('city', 0), ['aa', 'bb'], 33, ['pp', 'mm'], 'xxx', DateTime.now());

맵으로 만들기

final m = user.toJson();

문자로 만들기

final s = jsonEncode(m);

전송하기(Post)

await http.post(url, body: s);

아쉽게도 서버측에서는 값이 찍히지 않습니다.

컨텐츠타입이 정해지지 않아서 서버측 json 파서가 잘라내지를 못한 것입니다.

await http.post(url, headers: {'Content-Type': 'application/json'}, body: s);

json이라는 것을 명시해주면 잘 전송되는 것을 확인할 수 있습니다.

요약

  • 변환: 클래스(class) > 맵(Map<String, dynamic>) > 문자(String)
  • 방법: class > toJson > jsonEncode

영상

댓글남기기