Business. Fashow
Business. Fashow

Reputation: 39

How to parse complex json data in flutter and assign to a model?

This the method I used to fetch the data from an api and then assigning them to a model.

    var headers = {
      'API-Key': 'TEST_f+y9/tHG+yVxEq3uS3H1ogfezHSCWSq5MsIXUOnIV+Q',
      'Content-Type': 'application/json',
    };
    var data = '"shipment": {
    "validate_address": "no_validation",
    "ship_to": {
      "name": "Amanda Miller",
      "phone": "555-555-5555",
      "address_line1": "525 S Winchester Blvd",
      "city_locality": "San Jose",
      "state_province": "CA",
      "postal_code": "95128",
      "country_code": "US",
      "address_residential_indicator": "yes"
    },
    "ship_from": {
      "company_name": "Example Corp.",
      "name": "John Doe",
      "phone": "111-111-1111",
      "address_line1": "4009 Marathon Blvd",
      "address_line2": "Suite 300",
      "city_locality": "Austin",
      "state_province": "TX",
      "postal_code": "78756",
      "country_code": "US",
      "address_residential_indicator": "no"
    },
    "packages": [
      {
        "weight": {
          "value": 1.0,
          "unit": "ounce"
        }
      }
    ]
  }
}';

    final response = await http.post('https://api.shipengine.com/v1/rates', headers: headers, body: data);

    if (response.statusCode == 200) {
      String responseBody = response.body;
      var data = json.decode(responseBody);
      print(data);
        print(data["rate_response"]["rates"]);
      ResRate rates = new ResRate.fromJson(data);
      print(rates.rates[0].amount);
    } else {
      print(response.statusCode);
      print(response.body);
    }
  }

The is model.dart


 // Amount amount;
  List<Rates> rates;

  ResRate({
   // this.amount,
    this.rates});

  factory ResRate.fromJson(Map<String, dynamic> parsedJson){

    var list = parsedJson['rates'] as List;
    List<Rates> rates = list.map((i) => Rates.fromJson(i)).toList();


    return ResRate(

     //   amount: Amount.fromJson(parsedJson['amount']),
        rates: rates

    );
  }
}



class Amount{
  var currency;
  String amount;

  Amount({this.currency,
    this.amount});

  factory Amount.fromJson(Map<String, dynamic> parsedJson){
    return Amount(
      currency: parsedJson['currency'],
      amount : parsedJson['amount'],
    );
  }

}

class Rates{
  var rate_id;
  var rate_type;
   var carrier_id;
  Amount amount;

  //List<Amount> shipping_amount;

  Rates({
    this.rate_id, this.amount,
      this.rate_type, this.carrier_id,

  });

  factory Rates.fromJson(Map<String, dynamic> parsedJson){

  //  var list = parsedJson['images'] as List;
   // List<Image> images = list.map((i) => Image.fromJson(i)).toList();


    return Rates(
        rate_id: parsedJson['rate_id'],
      rate_type: parsedJson['rate_type'],
      carrier_id: parsedJson['carrier_id'],

      amount: Amount.fromJson(parsedJson['shipping_amount']),
    );
  }
}

But I'm getting error like this in my console.

Unhandled Exception: NoSuchMethodError: The method 'map' was called on null which points toward the model code below


    var list = parsedJson['rates'] as List;
    List<Rates> rates = list.map((i) => Rates.fromJson(i)).toList();

I tried printing the response body and the response body is fetched successfully and prints in the console.The object rates is also fetched in the response. But appears null .As This response is a complex one , rates too has objects.Here's the response fetched from the api.

  "rate_response": {
    "rate_request_id": 501834,
    "shipment_id": "se-2127183",
    "status": "completed",
    "created_at": "2019-07-26T22:10:50.286Z",
    "rates": [
      {
        "rate_id": "se-11744390",
        "rate_type": "shipment",
        "carrier_id": "se-123890",
        "shipping_amount": {
          "currency": "usd",
          "amount": 9.37
        },
        "insurance_amount": {
          "currency": "usd",
          "amount": 0.00
        },
        "confirmation_amount": {
          "currency": "usd",
          "amount": 0.00
        },
        "other_amount": {
          "currency": "usd",
          "amount": 0.00
        },
        "delivery_days": 3,
        "guaranteed_service": false,
        "estimated_delivery_date": "2019-07-26T05:00:00.000Z",
        "carrier_delivery_days": "Friday by 11:00 PM",
        "ship_date": "2019-07-26T05:00:00.000Z",
        "negotiated_rate": false,
        "service_type": "UPS® Ground",
        "service_code": "ups_ground",
        "trackable": true,
        "validation_status": "valid",
        "warning_messages": [],
        "error_messages": [],
        "carrier_code": "ups",
        "carrier_nickname": "UPS-28A1R9",
        "carrier_friendly_name": "UPS"
      }
    ],
    "invalid_rates": []
  },
  "shipment_id": "se-2127183",
  "carrier_id": "",
  "external_shipment_id": null,
  "ship_date": "2019-07-26T05:00:00.000Z",
  "created_at": "2019-07-26T22:10:50.286Z",
  "modified_at": "2019-07-26T22:10:50.286Z",
  "shipment_status": "pending",
  "ship_to": {
    "name": "Amanda Miller",
    "phone": "555-555-5555",
    "address_line1": "525 S Winchester Blvd",
    "city_locality": "San Jose",
    "state_province": "CA",
    "postal_code": "95128",
    "country_code": "US",
    "address_residential_indicator": "yes"
  },
  "ship_from": {
    "company_name": "Example Corp.",
    "name": "John Doe",
    "phone": "111-111-1111",
    "address_line1": "4009 Marathon Blvd",
    "address_line2": "Suite 300",
    "city_locality": "Austin",
    "state_province": "TX",
    "postal_code": "78756",
    "country_code": "US",
    "address_residential_indicator": "no"
  },
  "return_to": {
    "company_name": "Example Corp.",
    "name": "John Doe",
    "phone": "111-111-1111",
    "address_line1": "4009 Marathon Blvd",
    "address_line2": "Suite 300",
    "city_locality": "Austin",
    "state_province": "TX",
    "postal_code": "78756",
    "country_code": "US",
    "address_residential_indicator": "no"
  },
  "confirmation": "none",
  "advanced_options": {
    "bill_to_account": null,
    "bill_to_country_code": null,
    "bill_to_party": null,
    "bill_to_postal_code": null,
    "contains_alcohol": false,
    "custom_field1": null,
    "custom_field2": null,
    "custom_field3": null,
    "non_machinable": false,
    "saturday_delivery": false
  },
  "insurance_provider": "none",
  "tags": [],
  "total_weight": {
    "value": 1.00,
    "unit": "ounce"
  },
  "packages": [
    {
      "weight": {
        "value": 1.00,
        "unit": "ounce"
      },
      "dimensions": {
        "unit": "inch",
        "length": 0.0,
        "width": 0.0,
        "height": 0.0
      },
      "insured_value": {
        "currency": "usd",
        "amount": 0.0
      }
    }
  ]
}


Upvotes: 1

Views: 87

Answers (1)

Business. Fashow
Business. Fashow

Reputation: 39

I found a fix myself turns out I needed to add the sublist and the object header from the array while mapping in the model.

\\replace this 
    var list = parsedJson['rates'] as List;
\\with this
    var list = parsedJson["rate_response"]['rates'] as List;

    List<Rates> rates = list.map((i) => Rates.fromJson(i)).toList();

Upvotes: 1

Related Questions