Show POCO names instead of DataMember names

This one is probably a very obvious one, but I couldn’t find an answer in my searching.

I have POCO decotrated with DataContract/DataMember Attributes:

[DataContract]
    public class PeopleSoftLocation
    {
        [DataMember(Name = "Location ID")]
        public string LocationId { get; set; }
        [DataMember(Name = "Location Name")]
        public string LocationName { get; set; }
       ...
    }

The source of the data is a json text file, which I deserialize with StreamReader and .FromJson<PepoleSoftLocation>… The source data is using the DataMember names, but I want to display the original contract names in the resulting service… What do I need to do to make that happen?

The [DataMember(Name)] is an alias that overrides what gets serialized, it’s not possible to use the original name in serialization where you’ve told it to use an alias. If you want the original property names you can just use reflection, e.g:

var propNames = typeof(PeopleSoftLocation).GetProperties().Select(x => x.Name);

So given this sequence of events:

JSON text file with bad field names -> deserialize into POCO with correct field names -> reserialize into JSON for service endpoint

Is ServiceStack.Text the appropriate library to do the field remapping (presumably via a custom Deserialization function?) or should I just use JSON.NET (via CustomContractResolver) to map the bad fields to my POCO? In either case, I would remove the [DataMember(Name)] attributes so that the model is the way I want it.

Actually the fields above are bad examples, since I think ServiceStack.Text parses those just fine. There are some fields that I have to rename completely:

 [DataMember(Name="PrefFirstName")]
 public string PreferredFirstName { get; set; }

The way to do this with ServiceStack.Text is to defined a typed POCO with your bad field names as aliases then use AutoMapping to populate a Typed POCO without aliases and return that.

You can do this with 2 separate models, e.g

[DataContract]
public class PeopleSoftLocationSource 
{
    [DataMember(Name = "Location ID")]
    public string LocationId { get; set; }
}

public class PeopleSoftLocation
{
    public string LocationId { get; set; }
}

var fromDto = json.FromJson<PeopleSoftLocationSource>();
var toDto = fromDto.ConvertTo<PeopleSoftLocation>();

Or if you prefer you could inherit the POCO without aliases and dynamically add the aliases at runtime, e.g:

public class PeopleSoftLocationSource : PeopleSoftLocation {}

typeof(PeopleSoftLocationSource)
    .GetProperty(nameof(PeopleSoftLocation.LocationId))
    .AddAttributes(new DataMemberAttribute { Name = "Location ID" });
1 Like

Thanks mythz… One last question… Do I opt-in for DataMember/DataContract for both models, or can I get away with just using it for the source model? Wasn’t sure why I needed DataContract for the output model.

Just the models where you’re using any [DataMember] attributes, so only PeopleSoftLocationSource in this case.

1 Like