0

I am having this problem converting the following json to TodayWeather entity. How can I use the named constructor TodayHours?

I've been looking for a solution for this issue for a few days now, but I haven't found much, please guide me.

enter image description here

JSON:

 {
    "days": [
        {
            "datetime": "2023-01-05",
            "datetimeEpoch": 1672864200,
            "tempmax": 8.8,
            "tempmin": 2.3,
            "temp": 5.3,
            "windspeed": 8.6,
            "winddir": 223.9,
            "visibility": 19.7,
            "sunrise": "06:43:43",
            "sunset": "16:30:24",
            "conditions": "Snow, Rain, Overcast",
            "hours": [
                {
                    "datetime": "00:00:00",
                    "datetimeEpoch": 1672864200,
                    "temp": 4.4,
                    "humidity": 27.65,
                    "windspeed": 6.5,
                    "winddir": 249.2,
                    "visibility": 24.1,
                    "conditions": "Partially cloudy"
                },
                {
                    "datetime": "01:00:00",
                    "datetimeEpoch": 1672864200,
                    "temp": 4.4,
                    "humidity": 27.65,
                    "windspeed": 6.5,
                    "winddir": 249.2,
                    "visibility": 24.1,
                    "conditions": "Partially cloudy"
                }
            ]
        }
    ]
}

And my TodayWeather entity is:

 class TodayWeather {
  final String datetime;
  final num dateEpoch;
  final String conditions;
  final num tempMax;
  final num tempMin;
  final num windDir;
  final num windSpeed;
  final String sunRise;
  final String sunSet;
  final num humidity;
  final num visibility;
  final List<TodayHourse> hours;

  TodayWeather.fromJson(Map<String, dynamic> json)
      : datetime = json['days'][0]['datetime'],
        dateEpoch = json['days'][0]['datetimeEpoch'],
        conditions = json['days'][0]['conditions'],
        tempMax = json['days'][0]['tempmax'],
        tempMin = json['days'][0]['tempmin'],
        windDir = json['days'][0]['winddir'],
        windSpeed = json['days'][0]['windspeed'],
        sunRise = json['days'][0]['sunrise'],
        sunSet = json['days'][0]['sunset'],
        humidity = json['days'][0]['humidity'],
        visibility = json['days'][0]['visibility'],
        hours = List<TodayHourse>.from(
            json['days'][0]['hours'].map((x) => x.toJson())).toList();
}

This is my TodayHours entity:

 class TodayHourse {
  final String datetime;
  final num dateEpoch;
  final String conditions;
  final num temp;
  final num windDir;
  final num windSpeed;
  final num humidity;
  final num visibility;

  Map<String, dynamic> toJson() => {
        'datetime': datetime,
        'datetimeEpoch': dateEpoch,
        'conditions': conditions,
        'temp': temp,
        'winddir': windDir,
        'windspeed': windSpeed,
        'humidity': humidity,
        'visibility': visibility
      };

  TodayHourse.fromJson(Map<String, dynamic> json)
      : datetime = json['days'][0]['datetime'],
        dateEpoch = json['days'][0]['datetimeEpoch'],
        conditions = json['days'][0]['conditions'],
        temp = json['days'][0]['temp'],
        windDir = json['days'][0]['winddir'],
        windSpeed = json['days'][0]['windspeed'],
        humidity = json['days'][0]['humidity'],
        visibility = json['days'][0]['visibility'];
}

This method is parsing Json to TodayWeather:

@override
  Future<TodayWeather> getTodayWeather() async {
    final response = await httpClient.get(
        '36.31559%2C59.56796/today?unitGroup=metric&key=Key&contentType=json');
    validResponse(response);
    return TodayWeather.fromJson(response.data);
  }

3 Answers 3

1

First change your TodayHourse.fromJson to this:

TodayHourse.fromJson(Map<String, dynamic> json)
      : datetime = json['datetime'],
        dateEpoch = json['datetimeEpoch'],
        conditions = json['conditions'],
        temp = json['temp'],
        windDir = json['winddir'],
        windSpeed = json['windspeed'],
        humidity = json['humidity'],
        visibility = json['visibility'];

your hours is list of Map and you don't need to use json['days'][0]. Then in your TodayWeather.fromJson, change hours to this:

hours = (json['days'][0]['hours'] as List).map((x) => TodayHourse.fromJson(x)).toList();

you are using wrong function instead of toJson, you need to call TodayHourse.fromJson(x).

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much, my problem was solved with your detailed guidance.
1

Try to use this model:

class TodayWeather {
  TodayWeather({required this.days});

  final List<Day> days;

  factory TodayWeather.fromJson(Map<String, dynamic> json) => TodayWeather(
        days: List<Day>.from(json["days"].map((x) => Day.fromJson(x))),
      );
}

class Day {
  Day({
    required this.datetime,
    required this.datetimeEpoch,
    required this.tempmax,
    required this.tempmin,
    required this.temp,
    required this.windspeed,
    required this.winddir,
    required this.visibility,
    required this.sunrise,
    required this.sunset,
    required this.conditions,
    required this.hours,
  });

  final DateTime datetime;
  final int datetimeEpoch;
  final double tempmax, tempmin, temp, windspeed, winddir, visibility;
  final String sunrise, sunset, conditions;
  final List<Hour> hours;

  factory Day.fromJson(Map<String, dynamic> json) => Day(
        datetime: DateTime.parse(json["datetime"]),
        datetimeEpoch: json["datetimeEpoch"],
        tempmax: json["tempmax"].toDouble(),
        tempmin: json["tempmin"].toDouble(),
        temp: json["temp"].toDouble(),
        windspeed: json["windspeed"].toDouble(),
        winddir: json["winddir"].toDouble(),
        visibility: json["visibility"].toDouble(),
        sunrise: json["sunrise"],
        sunset: json["sunset"],
        conditions: json["conditions"],
        hours: List<Hour>.from(json["hours"].map((x) => Hour.fromJson(x))),
      );
}

class Hour {
  Hour({
    required this.datetime,
    required this.datetimeEpoch,
    required this.temp,
    required this.humidity,
    required this.windspeed,
    required this.winddir,
    required this.visibility,
    required this.conditions,
  });

  final int datetimeEpoch;
  final double temp, humidity, windspeed, winddir, visibility;
  final String datetime, conditions;

  factory Hour.fromJson(Map<String, dynamic> json) => Hour(
        datetime: json["datetime"],
        datetimeEpoch: json["datetimeEpoch"],
        temp: json["temp"].toDouble(),
        humidity: json["humidity"].toDouble(),
        windspeed: json["windspeed"].toDouble(),
        winddir: json["winddir"].toDouble(),
        visibility: json["visibility"].toDouble(),
        conditions: json["conditions"],
      );
}

Comments

1

First of all for more clear way to parse JSON arrays you can create helper method in your models, I call it Model.fromJsonList

 static List<WeatherDay> fromJsonList(dynamic jsonList) {
    if (jsonList == null || jsonList.isEmpty) return [];
    return (jsonList as List).map((e) => WeatherDay.fromJson(e)).toList();
  }

So by this method you can parse array response very easy and clean for example:

  Future<WeatherDay> fetchTodayWeather() async {
    final response = await httpClient.get(
        '36.31559%2C59.56796/today?unitGroup=metric&key=Key&contentType=json');
    final List<WeatherDay> weatherDays = WeatherDay.fromJsonList(response.data["days"]);
    return weatherDays.first;
  }

Totally we have:

class WeatherDay {
  WeatherDay( {
    @required this.datetime,
    @required this.hours,
  });

  final String datetime;
  final List<WeatherHour> hours;

  factory WeatherDay.fromJson(Map<String, dynamic> json) {
    return WeatherDay(
      datetime: json['datetime'] as String,
      hours: WeatherHour.fromJsonList(json['hours']),
    );
  }

  static List<WeatherDay> fromJsonList(dynamic jsonList) {
    if (jsonList == null || jsonList.isEmpty) return [];
    return (jsonList as List).map((e) => WeatherDay.fromJson(e)).toList();
  }
}

class WeatherHour {
  WeatherHour( {
    @required this.dateEpoch,
    @required this.conditions,
  });

  final num dateEpoch;
  final String conditions;

  factory WeatherHour.fromJson(Map<String, dynamic> json) {
    return WeatherHour(
      dateEpoch: json['datetimeEpoch'] as num,
      conditions: json['conditions'] as String,
    );
  }

  static List<WeatherHour> fromJsonList(dynamic jsonList) {
    if (jsonList == null || jsonList.isEmpty) return [];
    return (jsonList as List).map((e) => WeatherHour.fromJson(e)).toList();
  }
}

Note: I didn't parse all variable, do it by yourself.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.