Different type serialization for OrmLite versus web

I have a [Flags] enum that I would like to store in the database as an int (which as I understand it is the default behavior for enums with the [Flags] attribute). I have some request/response DTOs with properties of that enum type as well, but for these I want to serialize/deserialize the enum as a list of strings (so that the client doesn’t need to know the underlying int value of each flag in the enum).

When I configure JsConfig<T>.RawSerializeFn and JsConfig<T>.RawDeserializeFn to handle the conversion to and from string arrays for that enum type, the DTOs perform the conversion fine, but saving to the database starts failing with System.FormatException: Input string was not in a correct format I assume because those functions are also being applied to the enum when serializing to the database.

Is there an easy way around this (ie, some way to configure different serialization/deserialization behavior for the same type unde OrmLite and the rest of ServiceStack)? I could create my own extension methods to handle the conversion, but I feel like that would add a bunch of extra boilerplate/cruft to all my services that use that enum type in the DTO.

No there’s no distinct configuration of [Flag] Enums that can be configured differently in OrmLite and JsonSerializer.

But there’s already a Enum.ToList() extension method you can use to map a Flag enum to a List<string> so you can easily map it when you return a DTO, e.g:

return new Response {
    EnumsList = myEnum.ToList()
}

Thanks, I wasn’t aware of that extension method.

This raises another question for me–is there an easy way to do that kind of property conversion in an AutoQuery service? For example, if I had a setup like this:

[Flags]
public enum SmurfProperty {
  Smart = 0x1,
  Angry = 0x2,
  Timid = 0x4
}

public class Smurf {
  public Guid Id { get; set; }
  public string Name { get; set; }
  public SmurfProperty Properties { get; set; }
}

public class GetSmurfs : AutoQuery<Smurf> {}

…but I wanted the Properties field to serialize as a list in the response, what is the shortest path to make that happen? Here’s what I would have added currently, am I missing anything that could make this a little less verbose?:

public class SmurfResponse {
  public Guid Id { get; set; }
  public string Name { get; set; }
  public List<string> Properties { get; set; }
}

public class GetSmurfs : AutoQuery<Smurf, SmurfResponse> {}

public class SmurfService : Service
{
  public IAutoQuery AutoQuery { get; set; }

  public QueryResponse<SmurfResponse> Get(GetSmurfs request)
  {
    using(var db = DbFactory.OpenDbConnection()) {
      var query = AutoQuery.CreateQuery(request, Request.GetRequestParams());
      return new QueryResponse<SmurfResponse> {
        Offset = query.Offset.GetValueOrDefault(0),
        Total = (int) db.Count(query),
        Results = db.Select<Smurf>(query).Select(s => new SmurfResponse {
          Id = s.Id,
          Name = s.Name,
          Properties = s.Properties.ToList()
        }
      }
    }
  }
}

Since it’s stored as in int in the database when AutoQuery/OrmLite goes to map it to a different Model it’s trying to map an int (i.e. not the Enum).

One way that should work is to have a calculated property (and if you want you can ignore the existing Enum), e.g:

public class SmurfResponse
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    [IgnoreDataMember]
    public SmurfProperty Properties { get; set; }
    public List<string> PropertyNames { get { return Properties.ToList(); } }
}

This solution should work without needing a custom AutoQuery impl.

That looks good, thanks for the help.

After testing a bit, it looks like the ToList() extension method on enums returns a list of all possible flags in the base enum type, and not just the flags that are set in the current value.

For example, I would have expected SmurfProperty.Smart.ToList() to return ["Smart"], but instead it looks like it would return ["Smart", "Angry", "Timid"] (and return that same thing no matter the combination of flags you call ToList() on). Which is OK because I already had my own extension method that behaves the way I expected, but I just thought I’d mention it since it seems to be working differently than the way you had implied (and may be a bug).

Yep thx for the update, was just an Enum Extension I found after a quick scan, didn’t bother checking the impl - it returns all the enum names for that Enum as you’ve noticed :slight_smile: