def from_json(cls, json):
        articles = []

        for item in common.ensure_list(json):
            article = cls(
                id=item['ArticleID'],
                event_notification=item.get('EventNotification', None),
                product_name=item.get('ProductName', None),
                status=item.get('Status', None)
            )

            try:
                article.origin = Country(
                    item['OriginCountryCode'],
                    item['OriginCountry'],
                )
            except KeyError:
                pass

            try:
                article.destination = Country(
                    item['DestinationCountryCode'],
                    item['DestinationCountry'],
                )
            except KeyError:
                pass

            if item.get('EventCount', 0) > 0:
                article.events = Event.from_json(item['Events'])

            articles.append(article)
        return articles
    def from_json(cls, json):
        articles = []

        for item in common.ensure_list(json):
            article = cls(
                id=item["ArticleID"],
                event_notification=item.get("EventNotification", None),
                product_name=item.get("ProductName", None),
                status=item.get("Status", None),
            )

            try:
                article.origin = Country(item["OriginCountryCode"], item["OriginCountry"])
            except KeyError:
                pass

            try:
                article.destination = Country(item["DestinationCountryCode"], item["DestinationCountry"])
            except KeyError:
                pass

            if item.get("EventCount", 0) > 0:
                article.events = Event.from_json(item["Events"])

            articles.append(article)
        return articles
    def from_json(cls, json):
        tracking_results = []
        try:
            tracking_list = json['QueryTrackEventsResponse']['TrackingResult']
        except KeyError:
            raise Exception

        for item in common.ensure_list(tracking_list):
            tracking_result = cls(
                id=item['TrackingID'],
            )

            articles = Article.from_json(item.get('ArticleDetails', []))
            if len(articles) == 1:
                tracking_result.article = articles[0]
            else:
                raise common.AusPostException(
                    'found more than 1 article in JSON response'
                )

            if 'ConsignmentDetails' in item:
                consignment = Consignment.from_json(
                    item['ConsignmentDetails']
                )
                tracking_result.consignment = consignment

            tracking_results.append(tracking_result)

        return tracking_results
    def from_json(cls, json):
        articles = []

        for item in common.ensure_list(json):
            article = cls(id=item['ArticleID'],
                          event_notification=item.get('EventNotification',
                                                      None),
                          product_name=item.get('ProductName', None),
                          status=item.get('Status', None))

            try:
                article.origin = Country(
                    item['OriginCountryCode'],
                    item['OriginCountry'],
                )
            except KeyError:
                pass

            try:
                article.destination = Country(
                    item['DestinationCountryCode'],
                    item['DestinationCountry'],
                )
            except KeyError:
                pass

            if item.get('EventCount', 0) > 0:
                article.events = Event.from_json(item['Events'])

            articles.append(article)
        return articles
    def from_json(cls, json):
        try:
            result = json["PostcodeDeliveryCapabilities"]
            result = result["PostcodeDeliveryCapability"]
        except:
            raise Exception

        result = common.ensure_list(result)

        capabilities = []
        for item in result:
            utc_dt = common.get_aware_utc_datetime(item["LastModified"])
            capabilities.append(
                cls(postcode=item["Postcode"], last_modified=utc_dt, days=Day.from_json(item["WeekDay"]))
            )
        return capabilities
    def from_json(cls, json):
        try:
            res = json['DeliveryEstimateRequestResponse']['DeliveryEstimateDates']
            res = res['DeliveryEstimateDate']
        except KeyError:
            raise Exception

        res = common.ensure_list(res)

        dates = []
        for item in res:
            dates.append(cls(
                common.get_aware_utc_datetime(item['DeliveryDate']),
                item['NumberOfWorkingDays'],
                item['TimedDeliveryEnabled'],
            ))

        return dates
    def from_json(cls, json):
        events = []
        try:
            event_list = json["Event"]
        except KeyError:
            return events

        for item in common.ensure_list(event_list):
            event = cls(
                description=item["EventDescription"],
                timestamp=common.get_aware_utc_datetime(item["EventDateTime"]),
                location=item["Location"],
            )
            try:
                event.signer_name = item["SignerName"] or None
            except KeyError:
                pass
            events.append(event)
        return events
    def from_json(cls, json):
        events = []
        try:
            event_list = json['Event']
        except KeyError:
            return events

        for item in common.ensure_list(event_list):
            event = cls(
                description=item['EventDescription'],
                timestamp=common.get_aware_utc_datetime(item['EventDateTime']),
                location=item['Location'],
            )
            try:
                event.signer_name = item['SignerName'] or None
            except KeyError:
                pass
            events.append(event)
        return events
    def from_json(cls, json):
        try:
            result = json['PostcodeDeliveryCapabilities']
            result = result['PostcodeDeliveryCapability']
        except:
            raise Exception

        result = common.ensure_list(result)

        capabilities = []
        for item in result:
            utc_dt = common.get_aware_utc_datetime(item['LastModified'])
            capabilities.append(
                cls(
                    postcode=item['Postcode'],
                    last_modified=utc_dt,
                    days=Day.from_json(item['WeekDay']),
                ))
        return capabilities
    def from_json(cls, json):
        try:
            res = json['DeliveryEstimateRequestResponse'][
                'DeliveryEstimateDates']
            res = res['DeliveryEstimateDate']
        except KeyError:
            raise Exception

        res = common.ensure_list(res)

        dates = []
        for item in res:
            dates.append(
                cls(
                    common.get_aware_utc_datetime(item['DeliveryDate']),
                    item['NumberOfWorkingDays'],
                    item['TimedDeliveryEnabled'],
                ))

        return dates
    def from_json(cls, json):
        tracking_results = []
        try:
            tracking_list = json["QueryTrackEventsResponse"]["TrackingResult"]
        except KeyError:
            raise Exception

        for item in common.ensure_list(tracking_list):
            tracking_result = cls(id=item["TrackingID"])

            articles = Article.from_json(item.get("ArticleDetails", []))
            if len(articles) == 1:
                tracking_result.article = articles[0]
            else:
                raise common.AusPostException("found more than 1 article in JSON response")

            if "ConsignmentDetails" in item:
                consignment = Consignment.from_json(item["ConsignmentDetails"])
                tracking_result.consignment = consignment

            tracking_results.append(tracking_result)

        return tracking_results
    def from_json(cls, json):
        tracking_results = []
        try:
            tracking_list = json['QueryTrackEventsResponse']['TrackingResult']
        except KeyError:
            raise Exception

        for item in common.ensure_list(tracking_list):
            tracking_result = cls(id=item['TrackingID'], )

            articles = Article.from_json(item.get('ArticleDetails', []))
            if len(articles) == 1:
                tracking_result.article = articles[0]
            else:
                raise common.AusPostException(
                    'found more than 1 article in JSON response')

            if 'ConsignmentDetails' in item:
                consignment = Consignment.from_json(item['ConsignmentDetails'])
                tracking_result.consignment = consignment

            tracking_results.append(tracking_result)

        return tracking_results