Json to Model

Clean Code Big Poo·2023년 4월 10일
0

조각모음

목록 보기
2/3
post-thumbnail

Overview

개발을 하다보면 제일 귀찮은 것이 Model(Type)을 작성하는 것이다. Quick type을 사용하면 간단하게 모델을 작성할 수 있다.

Usage

다음은 날씨 API 의 response를 model 로 바꾸는 예시 이다.

url : http://api.weatherapi.com/v1/current.json?key=[API_KEY]&q=London&aqi=no

reponse를 복사 하여 Quick type에서 변환시켜 보자.

오른쪽의 창에서 언어를 선택하여 변환할 수 있다. Dart 언어 뿐 아니라 다양한 언어를 지원하고, 옵션도 지원한다. Dart의 경우에는 Null safetyf를 지원한다.

또한, 창의 Copy Code 버튼으로 간단한게 복사도 가능하다.

결과

// To parse this JSON data, do
//
//     final weatherModel = weatherModelFromJson(jsonString);

import 'dart:convert';

WeatherModel weatherModelFromJson(String str) => WeatherModel.fromJson(json.decode(str));

String weatherModelToJson(WeatherModel data) => json.encode(data.toJson());

class WeatherModel {
    WeatherModel({
        this.location,
        this.current,
    });

    Location? location;
    Current? current;

    factory WeatherModel.fromJson(Map<String, dynamic> json) => WeatherModel(
        location: json["location"] == null ? null : Location.fromJson(json["location"]),
        current: json["current"] == null ? null : Current.fromJson(json["current"]),
    );

    Map<String, dynamic> toJson() => {
        "location": location?.toJson(),
        "current": current?.toJson(),
    };
}

class Current {
    Current({
        this.lastUpdatedEpoch,
        this.lastUpdated,
        this.tempC,
        this.tempF,
        this.isDay,
        this.condition,
        this.windMph,
        this.windKph,
        this.windDegree,
        this.windDir,
        this.pressureMb,
        this.pressureIn,
        this.precipMm,
        this.precipIn,
        this.humidity,
        this.cloud,
        this.feelslikeC,
        this.feelslikeF,
        this.visKm,
        this.visMiles,
        this.uv,
        this.gustMph,
        this.gustKph,
    });

    int? lastUpdatedEpoch;
    String? lastUpdated;
    int? tempC;
    double? tempF;
    int? isDay;
    Condition? condition;
    double? windMph;
    double? windKph;
    int? windDegree;
    String? windDir;
    int? pressureMb;
    double? pressureIn;
    int? precipMm;
    int? precipIn;
    int? humidity;
    int? cloud;
    int? feelslikeC;
    double? feelslikeF;
    int? visKm;
    int? visMiles;
    int? uv;
    double? gustMph;
    double? gustKph;

    factory Current.fromJson(Map<String, dynamic> json) => Current(
        lastUpdatedEpoch: json["last_updated_epoch"],
        lastUpdated: json["last_updated"],
        tempC: json["temp_c"],
        tempF: json["temp_f"]?.toDouble(),
        isDay: json["is_day"],
        condition: json["condition"] == null ? null : Condition.fromJson(json["condition"]),
        windMph: json["wind_mph"]?.toDouble(),
        windKph: json["wind_kph"]?.toDouble(),
        windDegree: json["wind_degree"],
        windDir: json["wind_dir"],
        pressureMb: json["pressure_mb"],
        pressureIn: json["pressure_in"]?.toDouble(),
        precipMm: json["precip_mm"],
        precipIn: json["precip_in"],
        humidity: json["humidity"],
        cloud: json["cloud"],
        feelslikeC: json["feelslike_c"],
        feelslikeF: json["feelslike_f"]?.toDouble(),
        visKm: json["vis_km"],
        visMiles: json["vis_miles"],
        uv: json["uv"],
        gustMph: json["gust_mph"]?.toDouble(),
        gustKph: json["gust_kph"]?.toDouble(),
    );

    Map<String, dynamic> toJson() => {
        "last_updated_epoch": lastUpdatedEpoch,
        "last_updated": lastUpdated,
        "temp_c": tempC,
        "temp_f": tempF,
        "is_day": isDay,
        "condition": condition?.toJson(),
        "wind_mph": windMph,
        "wind_kph": windKph,
        "wind_degree": windDegree,
        "wind_dir": windDir,
        "pressure_mb": pressureMb,
        "pressure_in": pressureIn,
        "precip_mm": precipMm,
        "precip_in": precipIn,
        "humidity": humidity,
        "cloud": cloud,
        "feelslike_c": feelslikeC,
        "feelslike_f": feelslikeF,
        "vis_km": visKm,
        "vis_miles": visMiles,
        "uv": uv,
        "gust_mph": gustMph,
        "gust_kph": gustKph,
    };
}

class Condition {
    Condition({
        this.text,
        this.icon,
        this.code,
    });

    String? text;
    String? icon;
    int? code;

    factory Condition.fromJson(Map<String, dynamic> json) => Condition(
        text: json["text"],
        icon: json["icon"],
        code: json["code"],
    );

    Map<String, dynamic> toJson() => {
        "text": text,
        "icon": icon,
        "code": code,
    };
}

class Location {
    Location({
        this.name,
        this.region,
        this.country,
        this.lat,
        this.lon,
        this.tzId,
        this.localtimeEpoch,
        this.localtime,
    });

    String? name;
    String? region;
    String? country;
    double? lat;
    double? lon;
    String? tzId;
    int? localtimeEpoch;
    String? localtime;

    factory Location.fromJson(Map<String, dynamic> json) => Location(
        name: json["name"],
        region: json["region"],
        country: json["country"],
        lat: json["lat"]?.toDouble(),
        lon: json["lon"]?.toDouble(),
        tzId: json["tz_id"],
        localtimeEpoch: json["localtime_epoch"],
        localtime: json["localtime"],
    );

    Map<String, dynamic> toJson() => {
        "name": name,
        "region": region,
        "country": country,
        "lat": lat,
        "lon": lon,
        "tz_id": tzId,
        "localtime_epoch": localtimeEpoch,
        "localtime": localtime,
    };
}

Check Point

? 를 남발하게 되면 코딩할때 애로사항이 발생한다.(사용할 때 마다 일일히 널 체크를.... ㄷㄷㄷㄷ) 차라리 required 로 모두 변환시키고 서버에서 받은 값중에 null 값이 있다면 디폴트 값으로 변경해주는 것이 편안하다.

In Dart
A ?? B 는 'A가 null 값이면 B를 값으로 가진다'는 의미이다.
A != null ? B:C 는 'A가 null이 아니면 B값, A가 null이면 C값을 가진다'는 의미이다.

이를 활용하여 위의 결과를 예시로 보여주겠다.

//class location
class LocationModel {
 LocationModel({
   required this.name,
   required this.region,
   required this.country,
   required this.lat,
   required this.lon,
   required this.tzId,
   required this.localtimeEpoch,
   required this.localtime,
 });

 String name;
 String region;
 String country;
 double lat;
 double lon;
 String tzId;
 int localtimeEpoch;
 String localtime;

 factory LocationModel.fromJson(Map<String, dynamic> json) => LocationModel(
       name: json["name"] ?? '',
       region: json["region"] ?? '',
       country: json["country"] ?? '',
       lat: json["lat"] != null ? json["lat"].toDouble() : 0,
       lon: json["lon"] != null ? json["lon"].toDouble() : 0,
       tzId: json["tz_id"] ?? '',
       localtimeEpoch: json["localtime_epoch"] ?? 0,
       localtime: json["localtime"] ?? '',
     );

 Map<String, dynamic> toJson() => {
       "name": name,
       "region": region,
       "country": country,
       "lat": lat,
       "lon": lon,
       "tz_id": tzId,
       "localtime_epoch": localtimeEpoch,
       "localtime": localtime,
     };
}

이렇게 처리하면 서버에서 null값을 보내줄 때에도 문제없이 사용할 수 있다.

0개의 댓글