Sample ISerializer Implementation

This sample code illustrates a simple way to create your own serializer when using the Integration Framework. See Query Configuration For National Weather Service for additional information on the sample National Weather Service project.

The code sample provided here is set to a fixed width and does not wrap to allow you to copy and paste it into Visual Studio. You may need to expand your browser to view complete lines.

 namespace Sample.Connector.Weather
 {
     using System;
     using System.Collections.Generic;
     using System.Linq;
     using Sample.Connector.Weather.Models;
     using Simple.Connector.Framework;
 
     public class WeatherSerializer : ISerializer
     {
         // We do not need to implement this for this case because we do not have any target operations
         public string Serialize<T>(T typeToSerialize) { throw new System.NotImplementedException(); }
 
         public T Deserialize<T>(string s)
         {
             // We are only going to implement the one T, WeatherResponse.
             // If we had more to do, we would need to implement those.
             if (typeof(T) != typeof(WeatherResponse)) {  throw new NotImplementedException(); }
 
             // Implement our conversions
             // Step 1. Use the default conversion
             var xmlSerializer = new SimpleXmlSerializer();
             var rawData = xmlSerializer.Deserialize<dwml>(s);
 
             // Step 2. Take the default conversion and make it into something that is more consumable from Scribe Online
             var niceData = (T)(object)Translate(rawData);
             return niceData;
         }
 
         public static WeatherResponse Translate(dwml rawData)
         {
             var niceData = new WeatherResponse();
 
             var timelayout = rawData.data.timelayout.First(tl => tl.summarization == "24hourly");
 
             // This is a particularly difficult structure for us because
             // it is using an array of items that can be either a layout-key, start-valid-time or end-valid-time
             // AND the order is critical to understanding the periods of time.
             // For this implementation I am going to lean pretty heavily on LINQ,
             // but the key point is not this particular implementation -- the idea is that
             // whatever the complexity, you have to create some functionality that goes
             // from the type that can be generated to a type that plays better in Scribe Online.
 
             // Merge the type and data information
             var labelAndData = timelayout
                   .Items
                   .Zip(timelayout.ItemsElementName, (f, s) => new KeyValuePair<ItemsChoiceType, string>(s, f.ToString()));
 
             var times = labelAndData
                   .Aggregate(new TimeLayoutFold(), (state, a) => state.Combine(a))
                   .Layout.TimePeriods;
 
             var highs = rawData.data.parameters.temperature
                   .First(t => t.type == "maximum")
                   .value;
             var lows = rawData.data.parameters.temperature
                   .First(t => t.type == "minimum")
                   .value;
             var summaries = rawData.data.parameters.weather.weatherconditions;
 
             var weathers = times.Select((t,i) => new Weather
                                                        {
                                                          End = t.End,
                                                          Start = t.Start,
                                                          High = highs[i],
                                                          Low = lows[i],
                                                          Summary = summaries[i].weathersummary
                                                        });
 
             niceData.Weathers = weathers.ToArray();
             return niceData;
          }
      }
 
      public class TimePeriod
      {
          public DateTime Start { get; set; }
          public DateTime End { get; set; }
      }
 
      public class TimeLayout
      {
          public string Key { get; set; }
 
          public List<TimePeriod> TimePeriods { get; set; }
      }
 
      public class TimeLayoutFold
      {
          public TimeLayout Layout { get; set; }
 
          private DateTime? Start { get; set; }
 
          // This is an implementation that allows me to fold the different types that may be in the time-layouts
          // to create a well typed .NET version.
          public TimeLayoutFold Combine(KeyValuePair<ItemsChoiceType, string> input)
          {
              var newState = new TimeLayoutFold();
              switch (input.Key)
              {
                  case ItemsChoiceType.endvalidtime:
                         // We must assume that Start has already been set
                         if (!this.Start.HasValue)
                         {
                            throw new InvalidOperationException("The data was not in the format expected.");
                         }
 
                        var endDate = DateTime.Parse(input.Value);
                        var tp = new TimePeriod { Start = Start.Value, End = endDate };
 
                        newState.Start = null; // clear it out
                        newState.Layout = new TimeLayout
                                             {
                                                 Key = this.Layout.Key,
                                                 TimePeriods = this.Layout.TimePeriods
                                                                        .Concat(new [] {tp})
                                                                        .ToList()
                                             };
                        return newState;
 
                  case ItemsChoiceType.layoutkey:
 
                        newState.Start = this.Start;
                        newState.Layout = new TimeLayout { Key = input.Value, TimePeriods = new List<TimePeriod>() };
                        return newState;
 
                  case ItemsChoiceType.startvalidtime:
                       if (this.Start.HasValue)
                       {
                           throw new InvalidOperationException("The data was not in the format expected.");
                       }
 
                       var startDate = DateTime.Parse(input.Value);
                       newState.Start = startDate;
                       newState.Layout = new TimeLayout { Key = this.Layout.Key, TimePeriods = this.Layout.TimePeriods };
                      return newState;
                 default:
                     throw new ArgumentOutOfRangeException();
              }
          }
      }
  }

See Also

Building A TIBCO Scribe® Connector For National Weather Service