Home > Blockchain >  How to serialize/ make class for XML returned by API
How to serialize/ make class for XML returned by API

Time:01-20

I am calling an API that returns in XML format.

I have opted to keep the data in XML and not convert to Json.

I am receiving the data back and an instance of each list of data returned.

I have a basic XML class to take a piece of data from it.

I need to extend this to take a lat, long and some other data.

Is there an automated service for XML like Quicktype.io for Json? I am unable to find one and not sure how to structure my Class

This is my call

try{
    var response = await client.get(Uri.parse(
      'https_call'));   
    if (response.statusCode == 200) {
  
  final doc = XmlDocument.parse(utf8.decode(response.bodyBytes));
  final vehicleActivity = doc
      .findAllElements('VehicleActivity')
      .map((e) => VehicleActivity.fromElement(e))
      .toList();
  print(vehicleActivity);

Which functions.

My Class so far

import 'package:xml/xml.dart';

class VehicleActivity {
  VehicleActivity({
    this.recordedAtTime,
    this.itemIdentifier,
    this.validUntilTime,
  });

  DateTime? recordedAtTime;
  String? itemIdentifier;
  DateTime? validUntilTime;

  factory VehicleActivity.fromElement(XmlElement vaElement) => VehicleActivity(
        recordedAtTime: DateTime.parse(
          vaElement.findElements('RecordedAtTime').first.text,
        ),
        itemIdentifier: vaElement.findElements('ItemIdentifier').first.text,
        validUntilTime: DateTime.parse(
          vaElement.findElements('ValidUntilTime').first.text,
        ),
      );
}

Example of the XML returned (I need to call lat, long and some other data depending)

<VehicleActivity>
<RecordedAtTime>2022-01-18T14:16:17 00:00</RecordedAtTime>
<ItemIdentifier>f452f348-72f2-4bc4-b7d8-de65e591cf70</ItemIdentifier>
<ValidUntilTime>2022-01-18T14:22:14.063676</ValidUntilTime>
<MonitoredVehicleJourney>
<LineRef>4</LineRef>
<DirectionRef>inbound</DirectionRef>
<FramedVehicleJourneyRef>
<DataFrameRef>2022-01-18</DataFrameRef>
<DatedVehicleJourneyRef>4_20220118_14_15</DatedVehicleJourneyRef>
</FramedVehicleJourneyRef>
<PublishedLineName>4</PublishedLineName>
<OperatorRef>FTVA</OperatorRef>
<DestinationRef>4900801620</DestinationRef>
<VehicleLocation>
<Longitude>-0.720648</Longitude>
<Latitude>51.518651</Latitude>
</VehicleLocation>
<BlockRef>701130</BlockRef>
<VehicleRef>69388</VehicleRef>
</MonitoredVehicleJourney>
<Extensions>
<VehicleJourney>
<Operational>
<TicketMachine>
<TicketMachineServiceCode>B4</TicketMachineServiceCode>
<JourneyCode>1420</JourneyCode>
</TicketMachine>
</Operational>
<VehicleUniqueId>69388</VehicleUniqueId>
<DriverRef>701130</DriverRef>
</VehicleJourney>
</Extensions>
</VehicleActivity>

Thank you

Update Have attempted to build a class for extracting Lat,long. Error

    Exception Happened: Bad state: No element
    

Should String be Double?? I can't get double to function

import 'package:xml/xml.dart';
  
  class VehicleLocation{
    VehicleLocation({
    this.latitude,
    this.longitude,
    });
    
    String? latitude;
    String? longitude;

    factory VehicleLocation.fromElement(XmlElement vaElement) => VehicleLocation(
        latitude: vaElement.findElements('latitude').first.text,
        longitude: vaElement.findElements('longitude').first.text,
    );

  }

Adapted call testing for lat

final doc = XmlDocument.parse(utf8.decode(response.bodyBytes));
  final vehicleActivity = doc
      .findAllElements('Latitude')
      .map((e) => VehicleLocation.fromElement(e))
      .toList();
  print(vehicleActivity);

Update #2

I am calling the fetch and then implementing a mapmarker. The future to call and then place the marker is returning issues on vehicleactivity such as

    The type 'VehicleActivity' used in the 'for' loop must implement Iterable.
Future<void> showMapMarkers() async {
    _unTiltMap();

    var vehicleActivity = await fetchLiveLocations();
  for (VehicleActivity vehicleActivity in vehicleActivity!) {
    GeoCoordinates geoCoordinates = GeoCoordinates (vehicleActivity.latitude, vehicleActivity.latitude);
    
    _addMapMarker(geoCoordinates, 1);
  
  }
}

This same method has worked well for me with different API calls returning Json. Thank you

CodePudding user response:

Update you class to:

class VehicleActivity {
  VehicleActivity({
    this.recordedAtTime,
    this.itemIdentifier,
    this.validUntilTime,
    this.latitude,
  });

  DateTime? recordedAtTime;
  String? itemIdentifier;
  DateTime? validUntilTime;
  double? latitude;

  factory VehicleActivity.fromElement(XmlElement vaElement) => VehicleActivity(
        recordedAtTime: DateTime.parse(
          vaElement.findElements('RecordedAtTime').first.text,
        ),
        itemIdentifier: vaElement.findElements('ItemIdentifier').first.text,
        validUntilTime: DateTime.parse(
          vaElement.findElements('ValidUntilTime').first.text,
        ),
        latitude:
            double.tryParse(vaElement.findAllElements('Latitude').first.text),
      );
}

Notice that you need to use findAllElements because Latitude is inside a tag <VehicleLocation>. Equally, you could find the VehicleLocation tag and then find the lat/long tags inside that.

I think it would help you to visualise the data better if you format the XML (say in your IDE or browser) to indent it in the traditional way.

            <VehicleActivity>
                <RecordedAtTime>2021-12-03T18:10:01 00:00</RecordedAtTime>
                <ItemIdentifier>ad2c7031-ceac-4e7c-bc0c-9e667ad00dfe</ItemIdentifier>
                <ValidUntilTime>2021-12-03T18:16:05.408968</ValidUntilTime>
                <MonitoredVehicleJourney>
                    <LineRef>4</LineRef>
                    <DirectionRef>inbound</DirectionRef>
                    <FramedVehicleJourneyRef>
                        <DataFrameRef>2021-12-03</DataFrameRef>
                        <DatedVehicleJourneyRef>4_20211203_18_04</DatedVehicleJourneyRef>
                    </FramedVehicleJourneyRef>
                    <PublishedLineName>4</PublishedLineName>
                    <OperatorRef>FTVA</OperatorRef>
                    <DestinationRef>03700324</DestinationRef>
                    <VehicleLocation>
                        <Longitude>-0.719601</Longitude>
                        <Latitude>51.520305</Latitude>
                    </VehicleLocation>
                    <Bearing>30.0</Bearing>
                    <BlockRef>801312</BlockRef>
                    <VehicleRef>69921</VehicleRef>
                </MonitoredVehicleJourney>
  •  Tags:  
  • Related