jsonschema2pojo generating enum without any key value pairs

3.7k views Asked by At

I am using jsonschema2pojo to generate POJO from my JSON schema. However, it does not seem to be working when I am using named enums. Instead of the key value pairs in the POJO, it just adds __EMPTY__.

Is there a problem with the way I have specified the enums or is it an issue with jsonschema2pojo?

JSON schema:

{
    "type": "object",
    "$schema": "http://json-schema.org/draft-04/schema",
    "description": "Status identifier",
    "properties": {
        "status": {
            "type": "string",
            "enum": [
                {"ACTIVE" : 0},
                {"INACTIVE" : 1}
            ],

            "description": "Defines whether  schedule is active"
        }
    }
}

Generated Java POJO

import java.util.HashMap;
 import java.util.Map;
 import javax.annotation.Generated;
 import com.fasterxml.jackson.annotation.JsonAnyGetter;
 import com.fasterxml.jackson.annotation.JsonAnySetter;
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import com.fasterxml.jackson.annotation.JsonValue;
 import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.apache.commons.lang.builder.ToStringBuilder;

/**
 * Status identifier
 * 
 */

@JsonInclude(JsonInclude.Include.NON_NULL)

@Generated("org.jsonschema2pojo")

@JsonPropertyOrder({

"status"
}
) public class Testenum {
  /**
     * Defines whether  schedule is active
     * 
     */
  @JsonProperty("status")

private Testenum.Status status;
  @JsonIgnore

private Map<String, Object> additionalProperties=new HashMap<String, Object>();
  /**
     * Defines whether  schedule is active
     * 
     * @return
     *     The status
     */
  @JsonProperty("status")

public Testenum.Status getStatus() {
    return status;
  }
  /**
     * Defines whether  schedule is active
     * 
     * @param status
     *     The status
     */
  @JsonProperty("status")

public void setStatus(Testenum.Status status) {
    this.status=status;
  }
  @Override

public String toString() {
    return ToStringBuilder.reflectionToString(this);
  }
  @JsonAnyGetter

public Map<String,
  Object> getAdditionalProperties() {
    return this.additionalProperties;
  }
  @JsonAnySetter

public void setAdditionalProperty(String name,
  Object value) {
    this.additionalProperties.put(name, value);
  }
  @Override

public int hashCode() {
    return new HashCodeBuilder().append(status).append(additionalProperties).toHashCode();
  }
  @Override

public boolean equals(Object other) {
    if (other==this) {
      return true;
    }
    if ((other instanceof Testenum)==false) {
      return false;
    }
    Testenum rhs=((Testenum) other);
    return new EqualsBuilder().append(status,
    rhs.status).append(additionalProperties,
    rhs.additionalProperties).isEquals();
  }
  @Generated("org.jsonschema2pojo")

public static enum Status {
    __EMPTY__("", "");
    private final String value;
    private static Map<String, Testenum.Status> constants=new HashMap<String, Testenum.Status>();
    static {
      for (Testenum.Status c: values()) {
        constants.put(c.value, c);
      }
    }
    private Status(String value) {
      this.value=value;
    }
    @JsonValue

@Override

public String toString() {
      return this.value;
    }
    @JsonCreator

public static Testenum.Status fromValue(String value) {
      Testenum.Status constant=constants.get(value);
      if (constant==null) {
        throw new IllegalArgumentException(value);
      }
      else {
        return constant;
      }
    }
  }
}

Note - It works perfectly fine if I remove the enum names and just specify the values as below:

{
    "type": "object",
    "$schema": "http://json-schema.org/draft-04/schema",
    "description": "Status identifier",
    "properties": {
        "status": {
            "type": "string",
            "enum": [
                "ACTIVE" ,
                "INACTIVE" 
            ],

            "description": "Defines whether  schedule is active"
        }
    }
}
2

There are 2 answers

2
Eric McCormick On

[Edit]

TL;DR: By defining key-value pairs instead of a JSON array, your schema is not in fitting with json-schema.org's definition.

[/Edit]

In Java, an Enum is best used for either creating a singleton or enforcing a value from fixed number of constants. That fixed set of constants are effectively just a value list.

That being said, since your (first) JSON schema's definition of the status property is that it's a string and can be a value of a set of objects, as opposed to a value of a set of values. In other words, according to the documentation from jsonschema2pojo on defining with an enum, there is no example of a set of objects, only a set of values. It's expecting a list of values and nothing more.

Your example at the end of your question, "It works perfectly fine if i remove the enum names and just specify the values as below," your successful result is because you are defining the property to build out the enum according to what jsonschema2pojo is expecting.

My recommendation: Use your last example and then either build a separate Map<String, Integer> to pair the "Active" and "Inactive" values to their numeric representations (if you expect to have a larger list), or just set a couple constants that map to the numeric value (e.g.- private static int ACTIVE = 1;), as your needs may be.

0
Alexander Wessel On

I am using predefined enums for this purpose, with properties that look like this:

"organizationType" : {
    "javaType": "my.basepackage.api.enums.OrganizationType",
    "enum": ["AUTHORITY", "COMPANY"]
}

Then I handcraft my enum any way I like it. All you have to take care of, is to have matching enum value names in your Java enum and JSON schema. One downside of this approach, obviously, is that you cannot use something like a code value, such as "A" for AUTHORITY on in your JSON. You have to use, and thus expose, those enum names. But in my particular use case, you can transform those enum values to any code you like on the backend side of things, like the database:

public enum OrganizationType {
    AUTHORITY ("A", "Authority"),
    COMPANY   ("C", "Company");

    public final String code;
    public final String label;

    private OrganizationType(String code, String label) {
        this.code  = code;
        this.label = label;
    }
}

Finally, you can always use custom Annotators to get pretty much anything you can code out of JsonSchema2Pojo. So, if you can define what you need (even if it's contradicting a JSON schema rule you don't care about or want to bend to your needs), it's likely you can write a customization that works for you in little time. For me it turned out to be quite easy, and once you get your feet wet, you'll may come up much more quickly with a solution the next time you need something just a bit different than what the tool does out of the box. I've implemented an annotator for additional JSON-B property name annotations, giving me flexibility regarding the choice of parser, for example. Since I knew the customization patterns from earlier stuff, the decision to use customization was made quickly and implemented even quicker.