9

I have APEX classes defined with enum properties that are to be serialized into JSON. Also, I am reading in JSON and deserializing them back to my defined classes.

To make the enum properties work with the JSON transitions, I have created another Integer property that gets the ordinal of the enum and sets the enum based on the enum's values list. See below:

Enum definitions:

public enum DataSourceType {
    NA,
    ArbitronSummary,
    ArbitronTally,
    NielsenSummary,
    NielsenTally,
    Scarborough,
    Strata,
    None
}
public enum FilterJoinType {
    AndJoin,
    OrJoin,
    NotJoin
}
public enum HourByHourInterval {
    NA0,
    NA1,
    Quarterly,
    NA3,
    Hourly
}

APEX Class definitions:

public class HourByHourRequest {
    public List<String> Books { get; set; }
    public DataSourceType eDataSource { get; set; }
    public Integer DataSource {
        get {
            if (eDataSource == null)
                return 0;
            return eDataSource.ordinal();
        }
        set {
            eDataSource = lib_ap.DataSourceType.values()[value];
        }
    }
    public FilterJoinType eFilterJoinType { get; set; }
    public Integer FilterJoinType {
        get {
            if (eFilterJoinType == null)
                return 0;
            return eFilterJoinType.ordinal();
        }
        set {
            eFilterJoinType = lib_ap.FilterJoinType.values()[value];
        }
    }
    public HourByHourInterval eInterval { get; set; }
    public Integer Interval {
        get {
            if (eInterval == null)
                return 0;
            return eInterval.ordinal();
        }
        set {
            eInterval = lib_ap.HourByHourInterval.values()[value];
        }
    }
}

APEX code using the class to serialize to JSON and deserialize from JSON:

HourByHourRequest request = new HourByHourRequest();

request.Books = new List<String>();
request.Books.add('BookName');

request.eDataSource = DataSourceType.ArbitronTally;
request.eFilterJoinType = FilterJoinType.AndJoin;
request.eInterval = HourByHourInterval.Hourly;

String jsonStr = JSON.serialize(request);
HourByHourRequest request2 = (HourByHourRequest)JSON.deserialize(jsonStr, HourByHourRequest.class);

The reason why I used an Integer property to go with each enum property is because upon serializing to JSON the enum value is lost. So having the corresponding Integer value retains the value in JSON, which can be deserialized back successfully... except in the code shown above. The above code will actually fail at the deserialize part due to a "Duplicate field" error for each of the enum/integer field pairs. Both the enum and integer fields are being included in the JSON string when serialized, even though only the integer field is retaining the value.

Sample JSON:

{"Interval":4,
"eInterval":{},
"FilterJoinType":0,
"eFilterJoinType":{},...

My question: Is there a way to ignore fields for serializing to JSON? That would resolve the "Duplicate field" error. Otherwise, how would I go about an appropriate way to handling enums when converting to/from JSON? Thanks!

13

Declare your member transient and the JSON serializer will ignore it. A quick validation in an anonymous block (yes, you can declare classes inside anonymous blocks!)

public enum Obscurity{ OBVIOUS, OPAQUE, WTF }
public class Thing{
    public Obscurity obscurityLevel;
    public transient Obscurity notSerialized;
}

Thing t = new Thing();
t.obscurityLevel = Obscurity.OBVIOUS;
t.notSerialized = Obscurity.OPAQUE;

System.debug(LoggingLevel.Error,JSON.serialize(t));

The debug log generated will be along the lines of:

11:24:33.092 (92520000)|USER_DEBUG|[11]|ERROR|{"obscurityLevel":{}}

Note that this will also prevent the enum from being kept in viewstate, and I believe also has some impact on Database.Batchable's state.

Another option is to coerce your object into a Map, which can be done with the builtin JSON methods, and then mutate the Map before re-serializing it with the desired state. This can be used to handle the bulk of the object via the standard JSON methods, but then specially handle the enum. I've found this much easier than using the JSONGenerator and JSONParser classes.

  • Thanks! The transient member declaration did the trick. – Joe Oct 21 '13 at 20:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.