2

I have the below model classes that are populated via a JSON request:

public class Driver
{
    public string driverId { get; set; }
    public string url { get; set; }
    public string givenName { get; set; }
    public string familyName { get; set; }
    public string dateOfBirth { get; set; }
    public string nationality { get; set; }
}

public class Constructor
{
    public string constructorId { get; set; }
    public string url { get; set; }
    public string name { get; set; }
    public string nationality { get; set; }
}

public class DriverStanding
{
    public string position { get; set; }
    public string points { get; set; }
    public string wins { get; set; }
    public Driver Driver { get; set; }
    public List<Constructor> Constructors { get; set; }
}

public class StandingsList
{
    public string season { get; set; }
    public string round { get; set; }
    public List<DriverStanding> DriverStandings { get; set; }
}

public class StandingsTable
{
    public string season { get; set; }
    public List<StandingsList> StandingsLists { get; set; }
}

public class MRData
{
    public string xmlns { get; set; }
    public string series { get; set; }
    public string url { get; set; }
    public string limit { get; set; }
    public string offset { get; set; }
    public string total { get; set; }
    public StandingsTable StandingsTable { get; set; }
}

public class RootObject
{
    public MRData MRData { get; set; }
}

I then have a simple class like this:

public class DriverResults
{
    public string Season { get; set; }
    public string Points { get; set; }
    public List<Driver> Driver { get; set; }
}

public class Driver
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

When I request the JSON the first set of classes are populated entirely. I want to take some properties from some class eg/RootObject.MRData.StandingsTable.Season = DriverResults.Season. Below is my property mapping

Driver Maps

givenName = FirstName

familyName = LastName

Points Maps

points = Points

Season Maps

season = Season

This is what I have tried so far but its null every time:

        Mapper.CreateMap<MVCF1.API.Driver, MVCF1.Models.Driver>()
            .ForMember(dest => dest.FirstName, opt => opt.MapFrom(src => src.givenName))
            .ForMember(dest => dest.LastName, opt => opt.MapFrom(src => src.familyName));

        Mapper.CreateMap<MVCF1.API.DriverStanding, MVCF1.Models.DriverResults>()
            .ForMember(dest => dest.Points, opt => opt.MapFrom(src => src.points));

        Mapper.CreateMap<MVCF1.API.StandingsList, MVCF1.Models.DriverResults>()
            .ForMember(dest => dest.Season, opt => opt.MapFrom(src => src.season));

        Mapper.CreateMap<MVCF1.API.RootObject, MVCF1.Models.DriverResults>();

I looked at custom type converters but was unsure how to use them from reading the documentation.

Please help, thanks.

UPDATE: Here is the JSON returned

{
   "MRData":{
      "StandingsTable":{
         "StandingsLists":[
            {
               "DriverStandings":[
                  {
                     "Constructors":[
                        {
                           "constructorId":"red_bull",
                           "name":"Red Bull",
                           "nationality":"Austrian",
                           "url":"http://en.wikipedia.org/wiki/Red_Bull_Racing"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1987-07-03",
                        "driverId":"vettel",
                        "familyName":"Vettel",
                        "givenName":"Sebastian",
                        "nationality":"German",
                        "url":"http://en.wikipedia.org/wiki/Sebastian_Vettel"
                     },
                     "points":"255",
                     "position":"1",
                     "wins":"5"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"ferrari",
                           "name":"Ferrari",
                           "nationality":"Italian",
                           "url":"http://en.wikipedia.org/wiki/Scuderia_Ferrari"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1981-07-29",
                        "driverId":"alonso",
                        "familyName":"Alonso",
                        "givenName":"Fernando",
                        "nationality":"Spanish",
                        "url":"http://en.wikipedia.org/wiki/Fernando_Alonso"
                     },
                     "points":"245",
                     "position":"2",
                     "wins":"3"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"lotus_f1",
                           "name":"Lotus F1",
                           "nationality":"British",
                           "url":"http://en.wikipedia.org/wiki/Lotus_F1"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1979-10-17",
                        "driverId":"raikkonen",
                        "familyName":"Räikkönen",
                        "givenName":"Kimi",
                        "nationality":"Finnish",
                        "url":"http://en.wikipedia.org/wiki/Kimi_R%C3%A4ikk%C3%B6nen"
                     },
                     "points":"198",
                     "position":"3",
                     "wins":"1"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"red_bull",
                           "name":"Red Bull",
                           "nationality":"Austrian",
                           "url":"http://en.wikipedia.org/wiki/Red_Bull_Racing"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1976-08-27",
                        "driverId":"webber",
                        "familyName":"Webber",
                        "givenName":"Mark",
                        "nationality":"Australian",
                        "url":"http://en.wikipedia.org/wiki/Mark_Webber"
                     },
                     "points":"167",
                     "position":"4",
                     "wins":"2"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"mclaren",
                           "name":"McLaren",
                           "nationality":"British",
                           "url":"http://en.wikipedia.org/wiki/McLaren"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1985-01-07",
                        "driverId":"hamilton",
                        "familyName":"Hamilton",
                        "givenName":"Lewis",
                        "nationality":"British",
                        "url":"http://en.wikipedia.org/wiki/Lewis_Hamilton"
                     },
                     "points":"165",
                     "position":"5",
                     "wins":"3"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"mclaren",
                           "name":"McLaren",
                           "nationality":"British",
                           "url":"http://en.wikipedia.org/wiki/McLaren"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1980-01-19",
                        "driverId":"button",
                        "familyName":"Button",
                        "givenName":"Jenson",
                        "nationality":"British",
                        "url":"http://en.wikipedia.org/wiki/Jenson_Button"
                     },
                     "points":"153",
                     "position":"6",
                     "wins":"2"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"ferrari",
                           "name":"Ferrari",
                           "nationality":"Italian",
                           "url":"http://en.wikipedia.org/wiki/Scuderia_Ferrari"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1981-04-25",
                        "driverId":"massa",
                        "familyName":"Massa",
                        "givenName":"Felipe",
                        "nationality":"Brazilian",
                        "url":"http://en.wikipedia.org/wiki/Felipe_Massa"
                     },
                     "points":"95",
                     "position":"7",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"mercedes",
                           "name":"Mercedes",
                           "nationality":"German",
                           "url":"http://en.wikipedia.org/wiki/Mercedes-Benz_in_Formula_One"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1985-06-27",
                        "driverId":"rosberg",
                        "familyName":"Rosberg",
                        "givenName":"Nico",
                        "nationality":"German",
                        "url":"http://en.wikipedia.org/wiki/Nico_Rosberg"
                     },
                     "points":"93",
                     "position":"8",
                     "wins":"1"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"lotus_f1",
                           "name":"Lotus F1",
                           "nationality":"British",
                           "url":"http://en.wikipedia.org/wiki/Lotus_F1"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1986-04-17",
                        "driverId":"grosjean",
                        "familyName":"Grosjean",
                        "givenName":"Romain",
                        "nationality":"French",
                        "url":"http://en.wikipedia.org/wiki/Romain_Grosjean"
                     },
                     "points":"90",
                     "position":"9",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"sauber",
                           "name":"Sauber",
                           "nationality":"Swiss",
                           "url":"http://en.wikipedia.org/wiki/Sauber"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1990-01-26",
                        "driverId":"perez",
                        "familyName":"Pérez",
                        "givenName":"Sergio",
                        "nationality":"Mexican",
                        "url":"http://en.wikipedia.org/wiki/Sergio_P%C3%A9rez"
                     },
                     "points":"66",
                     "position":"10",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"sauber",
                           "name":"Sauber",
                           "nationality":"Swiss",
                           "url":"http://en.wikipedia.org/wiki/Sauber"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1986-09-13",
                        "driverId":"kobayashi",
                        "familyName":"Kobayashi",
                        "givenName":"Kamui",
                        "nationality":"Japanese",
                        "url":"http://en.wikipedia.org/wiki/Kamui_Kobayashi"
                     },
                     "points":"58",
                     "position":"11",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"force_india",
                           "name":"Force India",
                           "nationality":"Indian",
                           "url":"http://en.wikipedia.org/wiki/Force_India"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1987-08-19",
                        "driverId":"hulkenberg",
                        "familyName":"Hülkenberg",
                        "givenName":"Nico",
                        "nationality":"German",
                        "url":"http://en.wikipedia.org/wiki/Nico_H%C3%BClkenberg"
                     },
                     "points":"49",
                     "position":"12",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"force_india",
                           "name":"Force India",
                           "nationality":"Indian",
                           "url":"http://en.wikipedia.org/wiki/Force_India"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1986-04-16",
                        "driverId":"resta",
                        "familyName":"di Resta",
                        "givenName":"Paul",
                        "nationality":"Scottish",
                        "url":"http://en.wikipedia.org/wiki/Paul_di_Resta"
                     },
                     "points":"46",
                     "position":"13",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"williams",
                           "name":"Williams",
                           "nationality":"British",
                           "url":"http://en.wikipedia.org/wiki/Williams_F1"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1985-03-09",
                        "driverId":"maldonado",
                        "familyName":"Maldonado",
                        "givenName":"Pastor",
                        "nationality":"Venezuelan",
                        "url":"http://en.wikipedia.org/wiki/Pastor_Maldonado"
                     },
                     "points":"43",
                     "position":"14",
                     "wins":"1"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"mercedes",
                           "name":"Mercedes",
                           "nationality":"German",
                           "url":"http://en.wikipedia.org/wiki/Mercedes-Benz_in_Formula_One"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1969-01-03",
                        "driverId":"michael_schumacher",
                        "familyName":"Schumacher",
                        "givenName":"Michael",
                        "nationality":"German",
                        "url":"http://en.wikipedia.org/wiki/Michael_Schumacher"
                     },
                     "points":"43",
                     "position":"15",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"williams",
                           "name":"Williams",
                           "nationality":"British",
                           "url":"http://en.wikipedia.org/wiki/Williams_F1"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1983-10-15",
                        "driverId":"bruno_senna",
                        "familyName":"Senna",
                        "givenName":"Bruno",
                        "nationality":"Brazilian",
                        "url":"http://en.wikipedia.org/wiki/Bruno_Senna"
                     },
                     "points":"30",
                     "position":"16",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"toro_rosso",
                           "name":"Toro Rosso",
                           "nationality":"Italian",
                           "url":"http://en.wikipedia.org/wiki/Scuderia_Toro_Rosso"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1990-04-25",
                        "driverId":"vergne",
                        "familyName":"Vergne",
                        "givenName":"Jean-Éric",
                        "nationality":"French",
                        "url":"http://en.wikipedia.org/wiki/Jean-%C3%89ric_Vergne"
                     },
                     "points":"12",
                     "position":"17",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"toro_rosso",
                           "name":"Toro Rosso",
                           "nationality":"Italian",
                           "url":"http://en.wikipedia.org/wiki/Scuderia_Toro_Rosso"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1989-07-01",
                        "driverId":"ricciardo",
                        "familyName":"Ricciardo",
                        "givenName":"Daniel",
                        "nationality":"Australian",
                        "url":"http://en.wikipedia.org/wiki/Daniel_Ricciardo"
                     },
                     "points":"10",
                     "position":"18",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"marussia",
                           "name":"Marussia",
                           "nationality":"Russian",
                           "url":"http://en.wikipedia.org/wiki/Marussia_F1"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1982-03-18",
                        "driverId":"glock",
                        "familyName":"Glock",
                        "givenName":"Timo",
                        "nationality":"German",
                        "url":"http://en.wikipedia.org/wiki/Timo_Glock"
                     },
                     "points":"0",
                     "position":"19",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"caterham",
                           "name":"Caterham",
                           "nationality":"Malaysian",
                           "url":"http://en.wikipedia.org/wiki/Caterham_F1"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1981-10-19",
                        "driverId":"kovalainen",
                        "familyName":"Kovalainen",
                        "givenName":"Heikki",
                        "nationality":"Finnish",
                        "url":"http://en.wikipedia.org/wiki/Heikki_Kovalainen"
                     },
                     "points":"0",
                     "position":"20",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"caterham",
                           "name":"Caterham",
                           "nationality":"Malaysian",
                           "url":"http://en.wikipedia.org/wiki/Caterham_F1"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1984-09-08",
                        "driverId":"petrov",
                        "familyName":"Petrov",
                        "givenName":"Vitaly",
                        "nationality":"Russian",
                        "url":"http://en.wikipedia.org/wiki/Vitaly_Petrov"
                     },
                     "points":"0",
                     "position":"21",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"lotus_f1",
                           "name":"Lotus F1",
                           "nationality":"British",
                           "url":"http://en.wikipedia.org/wiki/Lotus_F1"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1985-12-27",
                        "driverId":"ambrosio",
                        "familyName":"d'Ambrosio",
                        "givenName":"Jérôme",
                        "nationality":"Belgian",
                        "url":"http://en.wikipedia.org/wiki/J%C3%A9r%C3%B4me_d%27Ambrosio"
                     },
                     "points":"0",
                     "position":"22",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"marussia",
                           "name":"Marussia",
                           "nationality":"Russian",
                           "url":"http://en.wikipedia.org/wiki/Marussia_F1"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1990-02-15",
                        "driverId":"pic",
                        "familyName":"Pic",
                        "givenName":"Charles",
                        "nationality":"French",
                        "url":"http://en.wikipedia.org/wiki/Charles_Pic"
                     },
                     "points":"0",
                     "position":"23",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"hrt",
                           "name":"HRT",
                           "nationality":"Spanish",
                           "url":"http://en.wikipedia.org/wiki/Hispania_Racing"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1977-01-14",
                        "driverId":"karthikeyan",
                        "familyName":"Karthikeyan",
                        "givenName":"Narain",
                        "nationality":"Indian",
                        "url":"http://en.wikipedia.org/wiki/Narain_Karthikeyan"
                     },
                     "points":"0",
                     "position":"24",
                     "wins":"0"
                  },
                  {
                     "Constructors":[
                        {
                           "constructorId":"hrt",
                           "name":"HRT",
                           "nationality":"Spanish",
                           "url":"http://en.wikipedia.org/wiki/Hispania_Racing"
                        }
                     ],
                     "Driver":{
                        "dateOfBirth":"1971-02-24",
                        "driverId":"rosa",
                        "familyName":"de la Rosa",
                        "givenName":"Pedro",
                        "nationality":"Spanish",
                        "url":"http://en.wikipedia.org/wiki/Pedro_de_la_Rosa"
                     },
                     "points":"0",
                     "position":"25",
                     "wins":"0"
                  }
               ],
               "round":"18",
               "season":"2012"
            }
         ],
         "season":"2012"
      },
      "limit":"30",
      "offset":"0",
      "series":"f1",
      "total":"25",
      "url":"http://ergast.com/api/f1/current/driverstandings.json",
      "xmlns":"http://ergast.com/mrd/1.2"
   }
}
Jon
  • 38,814
  • 81
  • 233
  • 382

2 Answers2

2

When running the Assertion as advised by @David I get:

AutoMapper.AutoMapperConfigurationException : 
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
=================================================================================
DriverStanding -> DriverResults (Destination member list)
StackOverflow.Null.API.DriverStanding -> StackOverflow.Null.Models.DriverResults (Destination member list)
---------------------------------------------------------------------------------
Season
================================================================================
StandingsList -> DriverResults (Destination member list)
StackOverflow.Null.API.StandingsList -> StackOverflow.Null.Models.DriverResults (Destination member list)
--------------------------------------------------------------------------------
Points
Driver
=============================================================================
RootObject -> DriverResults (Destination member list)
StackOverflow.Null.API.RootObject -> StackOverflow.Null.Models.DriverResults (Destination member list)
-----------------------------------------------------------------------------
Season
Points
Driver

Now essentially you have an object (MRData) that has a list of objects (StandingsList) which has a list of objects (DriverStanding). I presume that when you apply the mapping, you want this 1 complex MRData object to be flattened to many DriverResults objects. This is not something you can do easily directly with a configuration, but you can by reapplying mapping on the various objects.

I think you're looking for something similar to this solution: AutoMapper and flattening nested arrays

UPDATE - Updated code to match updated requirements.

I have partially implemented that solution.

MVCF1Profile.cs

namespace MVCF1
{
    using System.Collections.Generic;

    using AutoMapper;

    public class MVCF1Profile : Profile
    {
        public override string ProfileName
        {
            get { return "MVCF1Profile"; }
        }

        protected override void Configure()
        {
            AllowNullDestinationValues = true;
            AllowNullCollections = true;

            CreateMap<API.Driver, Models.Driver>()
                .ForMember(dest => dest.FirstName, opt => opt.MapFrom(src => src.givenName))
                .ForMember(dest => dest.LastName, opt => opt.MapFrom(src => src.familyName));

            CreateMap<API.StandingsList, Models.DriverResults>()
                .ForMember(dest => dest.Driver, opt => opt.MapFrom(src => src.DriverStandings.Select(ds => Mapper.Map<API.Driver, Models.Driver>(ds.Driver))))
                .ForMember(dest => dest.Points, opt => opt.Ignore());
        }
    }
}

The unit tests:

[Test]
public void AutoMapper_Configuration_IsValid()
{
    Mapper.Initialize(m => m.AddProfile<MVCF1Profile>());
    Mapper.AssertConfigurationIsValid();
}

[Test]
public void AutoMapper_DriverMapping_IsValid()
{
    Mapper.Initialize(m => m.AddProfile<MVCF1Profile>());
    Mapper.AssertConfigurationIsValid();

    // Convert JSON string from question to RootObject instance
    var data = GetData();

    var ds = data.MRData.StandingsTable.StandingsLists.First();
    var driverResults = Mapper.Map<StandingsList, Models.DriverResults>(ds);

    Assert.That(driverResults, Is.Not.Null);
    Assert.That(driverResults.Points, Is.Null);
    Assert.That(driverResults.Season, Is.EqualTo("2012"));
    Assert.That(driverResults.Driver, Is.Not.Null);
    Assert.That(driverResults.Driver.Count(), Is.EqualTo(25));
}

For reference my GetData is (with json string above removed)

private RootObject GetData()
{
    string jsonMessage;

    #region Initialise String
    jsonMessage = @"";
    #endregion

    var data = JsonConvert.DeserializeObject<RootObject>(jsonMessage);

    Assert.That(data, Is.Not.Null);
    Assert.That(data, Is.InstanceOf<RootObject>());
    Assert.That(data.MRData, Is.Not.Null);
    Assert.That(data.MRData, Is.InstanceOf<MRData>());
    Assert.That(data.MRData.StandingsTable, Is.Not.Null);
    Assert.That(data.MRData.StandingsTable, Is.InstanceOf<StandingsTable>());

    return data;
}

You can apply the mapping for the higher level objects as required simply by calling the mapper again. For example, once you've fixed the configuration you can do:

Mapper.Map(root.MRData.StandingsTable, result);

This will map the appropriate fields from the StandingsTable into the result destination.

Community
  • 1
  • 1
Mightymuke
  • 5,094
  • 2
  • 31
  • 42
  • What I'm trying to do is take various property values at various points in the original class heirarchy to populate my DriverResults object – Jon Nov 16 '12 at 20:56
  • Its a bad name for an AutoMapper profile (and so is my namespace which is shown in the assertion message). Check out this [pretty good blog post](http://consultingblogs.emc.com/owainwragg/archive/2010/12/15/automapper-profiles.aspx) that describes profiles. – Mightymuke Nov 16 '12 at 20:58
  • Maybe I'll just use LINQ, might be easier – Jon Nov 17 '12 at 09:31
  • You would only ever have 1 set of results for a season. I would like one object returned of type DriverResults with the List of Drivers populated from the JSON. I have updated my question with an example of the JSON returned – Jon Nov 18 '12 at 10:44
  • OK, I've simplified it to give the result you're expecting. Left the mapping of `DriverResults.Points` to you as its at a higher level in the destination, so some calculation is required. – Mightymuke Nov 18 '12 at 23:15
1

Try something like this. You have to explicitly dig down into the src object for it to map properly. Automapper will only automatically match properties that have the same name and are on the same level of depth. If the names don't match or are nested within another you have to specify exactly which property you want. Lists of objects will map properly without altering the Mapper.CreateMap<>() but you have to map from single object to single object or list of objects to another list of objects.

For Example:

Mapper.CreateMap<MVCF1.API.RootObject, MVCF1.Models.DriverResults>()
    .ForMember(dest => dest.Season, opt.MapFrom(src => src.MRData.StandingsTable.season));
danseery
  • 486
  • 2
  • 11