6

This is my response at the moment... (from my RESTful API)

[
  {
    "batchID": 1,
    "status": "IN_PROGRESS"
  }
]

but what I really want is...

[
  {
    "batchID": 1,
    "status": 10   -- which means "In_progress" in my ENUM
  }
]

here is my c# DTO...

public class ReplyItem
{
    public int BatchID { get; set; }            
    public BatchStatusCodes Status { get; set; }
}

so in the JSON my BatchStatusCode is being serialized into a string, but I'd like it as an integer ,as the ENUM has each value set specifically (goes up in 5's)

One Solution : I know I can just change BatchStatusCodes to an int, and whenever I use it I could cast the ENUM to an integer, but including the ENUM in the reply makes it slightly more self describing.

I was hoping maybe I could use an Attribute or some such fancy trick, or maybe set a service wide variable to not treat enums as they currently are?

Ninjanoel
  • 2,864
  • 4
  • 33
  • 53
  • Please check this post, it may help you: [Forcing enum as integer in serialization][1] [1]: http://stackoverflow.com/questions/117348/can-you-force-the-serialization-of-an-enum-value-into-an-integer – TamerM Apr 22 '14 at 14:01
  • @TamerM that question isn't related to ServiceStack, and as ServiceStack has it's only serializer the standard Attributes and techniques described in that question do not apply. – Ninjanoel Apr 22 '14 at 14:22

3 Answers3

8

You can add a [Flags] attribute to enums you want to be treated as numbers, e.g:

[Flags]
BatchStatusCodes { ... } 

Otherwise you can get ServiceStack.Text to treat all enums as integers with:

JsConfig.TreatEnumAsInteger = true;
mythz
  • 141,670
  • 29
  • 246
  • 390
  • That's not what the Flags attribute is for though. FlagsAttribute means that an enum represents a bit field, meaning a set of numbers that can be combined. That specifically means enums with values like 1,2,4,8,16,etc. not enums with values like 1,2,3,etc. This might have the intended outcome, but it's for entirely the wrong reasons. – Mel Mar 03 '20 at 13:24
  • @Mel I'm well aware what the intention of the `[Flags]` attribute is, it's in the name! Which should be the only time you want to return a magic number across a service boundary, those that want to inconsistently force returning integer values for enums (by not just setting the global switch) can choose to use `[Flags]` to force adhoc enums serialized as integers. – mythz Mar 03 '20 at 14:06
1

<rant> Although, I would avoid using Magic Numbers at any cost. Just imagine you will need to support this service later and how are you supposed to remeber all those digits... </rant>

Anyway, you mat try telling SS to use UseBclJsonSerializers. In your AppHost configure method add this:

SetConfig(new HostConfig{
     // ...
     UseBclJsonSerializers = true,
     // ...
});
iamruss
  • 782
  • 4
  • 11
  • 1
    actually, maintainability is my goal here, it is better in the c# to use a self describing ENUM, and any c# clients connecting to this service would use the DTO library (which includes the ENUM), and any javascript clients could use the c# code as a document to create their own version of the required ENUM. Using strings instead of numbers feels a lot more error prone to me, what of case sensitivity? spelling mistakes? speed of comparing string vs comparing integers? All round I think the API should use numerals while programmers use ENUM's, allowing strings to represent numerals – Ninjanoel Apr 23 '14 at 08:27
  • @Nnoel would not worry much about string<->enum conversion speed without actually measuring it in your own application. most likely you will see other places where speed goes down and spending effort on those will allow you the luxury of having string values for enums. – iamruss Apr 23 '14 at 08:36
  • 1
    string to enum conversion speed? An enum allows me a 'token' that the compiler understands to mean a precise value of a ecomonical data type, I start typing ["in_pr"] and the compiler automatically wants to swop in "IN_PROGRESS", and if I spell it wrong, compiler helps me out, speed was a side issue, using an ENUM in this situation feels like the maintainable solution. – Ninjanoel Apr 23 '14 at 09:17
1

Old question, I know, but came up in my search for the same issue. If we have an

public eStatus Status { get; set; }

then we simply add an additional

public int StatusId => (int)Status;

(or public int StatusId { get { return (int)Status } } in old-speak)

You can always mark the original as non-serializable if you don't want it in your serialized output, although bear in mind that it won't deserialize from the number unless you create an equivalent setter.

JSobell
  • 1,825
  • 1
  • 14
  • 10