25

I am using org.json library to convert Object to Json format. Kindly check the below code snippet.

public enum JobStatus implements Serializable{
     INCOMPLETE,
     INPROGRESS,
     ABORTED,
     COMPLETED
}

public class Job implements Serializable {
    private string id;
    private JobStatus status;
    ...
}

...

// Create Job Object
Job job = new Job("12345", JobStatus.INPROGRESS);

// Convert and print in JSON format
System.out.println(new JSONObject(job).toString());

It shows the output like this :

 {"id":"12345", "status" : {}}

It shows blank and adds Curly bases. What does it mean? Is anybody gone through this problem?

Morez
  • 2,048
  • 5
  • 36
  • 49

5 Answers5

25

First of all I highly recommend do not use this library (org.json), this is very old and unsupported (as i know) library. I suggest Jackson or Gson.

But if you really need JSONObject, you can add getter into enum:

 public enum JobStatus implements Serializable{
    INCOMPLETE,
    INPROGRESS,
    ABORTED,
    COMPLETED;

    public String getStatus() {
        return this.name();
    }
}

result of serialization:

{"id":"12345","status":{"status":"INPROGRESS"}}

As I know, JSONObject don't support correct serialization of enums which not have any additional data inside.

Denys Denysiuk
  • 775
  • 5
  • 11
  • 1
    @Denya : Yeah you are right. org.json is too old. I will surely move to Gson or Jackson. Thank you for your valuable suggestions. – Morez Jun 17 '15 at 11:37
  • There is no need to implement Serializable because every enum is Serializable by default. – Tymur Berezhnoi Dec 07 '19 at 10:01
5
ObjectMapper mapper= new ObjectMapper();

new JSONObject(mapper.writeValueAsString(job));

would do the trick. Now Enums and DateTime types looks normal and is converted properly in json objects.

I came to this page as a person seeking answer and my research helped me to answer this question.

Machavity
  • 30,841
  • 27
  • 92
  • 100
Hari
  • 51
  • 1
  • 2
  • I tried this but it didn't work, the value in the JSON for me was blank. My enum is very simplistic though; does that make a difference? `public enum ServiceType { MULTI_MASTER, SINGLE_MASTER }` – Mike Stoddart Nov 06 '15 at 15:20
  • The above method helps you to convert an object of some class type to a JSON object without tampering any data types as we use ObjectMapper library. Since i dont know what you are doing with that JSON object, i can suggest you to debug line by line code in your IDE and find where your enum data gets lost. I hope you may need to check the code that manipulates the created JSON object. – Hari Nov 10 '15 at 16:19
3

It seems JSONObject doesn't support enums. You could alter your Job class to add a getter like this:

public String getStatus() {
    return status.name();
}

then, invoking new JSONObject(job).toString() produces:

{"id":"12345","status":"INPROGRESS"}
Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

for me, i made an interface that shuold be implemented by any enum i will have to use in Json, this interface forces the enum to know the proper enum itself from a value, and also it should return a value ... so every enum.CONSTANT is mapped to a value of any type (weather a number or a String)

so when i want to put this enum in a Json Object, i ask the enum.CONSTANT to give me it's value, and when i have this value (from Json), i can request from the enum to give me the proper enum.CONSTANT mapped to this value

the interface is as follows (you can copy it as it is) :

/**
 * 
 * this interface is intended for {@code enums} (or similar classes that needs
 * to be identified by a value) who are based on a value for each constant,
 * where it has the utility methods to identify the type ({@code enum} constant)
 * based on the value passed, and can declare it's value in the interface as
 * well
 * 
 * @param <T>
 *            the type of the constants (pass the {@code enum} as a type)
 * @param <V>
 *            the type of the value which identifies this constant
 */
public interface Valueable<T extends Valueable<T, V>, V> {

    /**
     * get the Type based on the passed value
     * 
     * @param value
     *            the value that identifies the Type
     * @return the Type
     */
    T getType(V value);

    /**
     * get the value that identifies this type
     * 
     * @return a value that can be used later in {@link #getType(Object)}
     */
    V getValue();
}

now here is an example for a small enum implementing this interface:

public enum AreaType implements Valueable<AreaType, Integer> {
    NONE(0),
    AREA(1),
    NEIGHBORHOOD(2);

    private int value;

    AreaType(int value) {
        this.value = value;
    }

    @Override
    public AreaType getType(Integer value) {

        if(value == null){
            // assume this is the default
            return NONE;
        }

        for(AreaType a : values()){
            if(a.value == value){ // or you can use value.equals(a.value)
                return a;
            }
        }
        // assume this is the default
        return NONE;
    }

    @Override
    public Integer getValue() {
        return value;
    }

}

to save this enum in a Json :

AreaType areaType = ...;
jsonObject.put(TAG,areaType.getValue());

now to get your value from a Json Object :

int areaValue = jsonObject.optInt(TAG,-1);
AreaType areaType = AreaType.NONE.getType(areaValue);

so if the areaValue is 1 for example, the AreaType will be "Area", and so on

Ahmed Adel Ismail
  • 2,168
  • 16
  • 23
0

Similar to what @Denys Denysiuk has answered. But if you want to return any value instead of String We can use like this. In below example i wanted to return value 1, or 15 instead of String

@Getter
public enum PaymentCollectionDay {

    FIRST_OF_MONTH(1), FIFTEENTH_OF_MONTH(15);
    PaymentCollectionDay(int day) {
        this.day = day;
    }

    @JsonValue
    final int day;
}
Niraj Sonawane
  • 10,225
  • 10
  • 75
  • 104