I've created a demo on persisting enumeration and sets to JSON format. The default Delphi RTL persists enumeration as their names.

The improvement I made persists enumerations and sets to any name you choose, subject to the rules of JSON.

It's up on Github, and it's named EnumJSON.

Here's a sample enum:

  TFunnyEnums = (Highlander, GalaxyFish, TomorrowNeverComes);

In order to persist this, inherit a new class from TEnumInterceptor, and use the EnumAs attribute with the output of the enum. One EnumAs attribute for one enum. So, here's the interceptor for TFunnyEnums:

  [EnumAs('High...lander!'), EnumAs('Galaxy Fish???'), EnumAs('James Bond!')]
  TFunnyEnumInterceptor1 = class(TEnumInterceptor<TFunnyEnums>)end; // just a plain descendant, no need to override anything

On a field that you want to output, use the JSONReflect atribute with your new TEnumInterceptor descendant:

    [JSONReflect(ctString, rtString, TFunnyEnumInterceptor1, nil, true)]
    FOption1: TFunnyEnums;

That's all you have to do. Now, when you use TJson.ObjectToJson on your class which has the enum field, it will output with what you declared on the interceptor.

For a set that looks like so:

  TEnum = (seOne, seTwo, seThree);
  TEnumSet = set of TEnum;

You override the TEnumSetInterceptor, like so:

  [EnumSetAs('Nine,Five,Four')] // Default separator is comma
  TEnumSetInterceptor2 = class(TEnumSetInterceptor<TEnumSet>)end;

So if your class contains the following definition:

   [JSONReflect(ctStrings, rtStrings, TEnumSetInterceptor1, nil, true), JSONName('EnumSet1')]
   FEnumSet1: TEnumSet;

Then, seOne will be output as Nine, seTwo will be output as Five, seThree will be output as Four. So if your set field contains seOne and seThree, expect to see  EnumSet1: ["Nine", "Four"] as the output.