joukevandermaas / saule

JSON API library for ASP.Net Web API 2.
https://joukevandermaas.github.io/saule
MIT License
76 stars 37 forks source link

Support mapping to custom names for properties #83

Open markwalsh-liverpool opened 8 years ago

markwalsh-liverpool commented 8 years ago

I have a requirement in certain areas of my application to map from a database object to a ApiResource. Sometimes, I wish to change the property name when returning the response, so for example, using the Person resource

public class PersonResource : ApiResource
{
    public PersonResource()
    {
        Attribute("FirstName");
        Attribute("LastName");
        Attribute("Age");
    }
}

The POCO I wish to convert from could be (notice the property entitled "Surname")

   public class Person
   {
        public string FirstName { get; set; }
        public string Surname { get; set; }
        public int Age { get; set; }
   }

Do you think it would be a good idea to support this via the WithAttribute method? Perhaps have an overloaded method which also takes the destination property name?

Something like this:

public class PersonResource : ApiResource
{
    public PersonResource()
    {
        Attribute("FirstName");
        Attribute("Surname", "LastName");
        Attribute("Age");
    }
}

Thanks

joukevandermaas commented 8 years ago

I think if this feature is added, it will not be a one-to-one mapping. In my opinion it should be a one-to-many mapping of 'resource property' to 'POCO property'. This way, you can serialize many classes with different property names into the same resource.

In order to make it nice, there will need to be some ergonomic APIs. I expect that the C# 6 nameof operator will make this a lot nicer/easier to use.

markwalsh-liverpool commented 8 years ago

That makes sense. I suppose with the overload you'd only be able to map from one class per resource, some people might want to map an "OtherPerson" class which has different property names.

I think in order to achieve this we might need to use Attributes on the POCO to signify which each property maps to in the ApiResource and the output property name. I am just brainstorming this though. I am unsure whether there's another way by somehow passing some sort of mapping interface.

joukevandermaas commented 8 years ago

I don't like attributes on POCOs. In fact, this is one of the most important reasons for the existence of ApiResource. If the API allowed users to specify a list of valid property names for an attribute/relationship, I don't think they'd be necessary:

Attribute("LastName", new [] {
    "Surname", "FamilyName", "Name"
});

Saule could take the property value of LastName, Surname, FamilyName and Name (in that order) and serialize it as an attribute called last-name. Even better would be to pass a lambda:

Attribute("LastName", (obj) => (obj as Person)?.Surname);

Although that's admittedly only really nice in C# 6.