Custom JAX-RS annotation when generating jax-rs from raml


#1

Hi, guys. I have a raml and want to generate jax-rs, but I want to cusom the generated jackson annotation on Java Object. For example, I have a raml as following

   #%RAML 0.8
   title: Note
   version: 1
   baseUri: http://www.test.com
   mediaType: application/json

schemas:
  - NoteDTO: !include NoteDTO.json
  - NotesDTO: !include NotesDTO.json


resourceTypes:
    - Collection:
        post:
          body:
            application/json:
              schema: <<item>>
          responses:
            201:
              body:
                application/json:
                  schema: <<items>>


/notes:
  type:  { Collection: {item : NoteDTO, items : NotesDTO} }
  /{crId}:
    get:
      responses:
        200:
          body:
            application/json:
              schema: NotesDTO

Then the Java Object is as following:

JsonInclude(JsonInclude.Include.NON_NULL)
@Generated("org.jsonschema2pojo")
@JsonPropertyOrder({
    "id",
    "type",
    "crId",
    "content",
    "createdTime",
    "creatorId",
    "creatorName"
})
public class NoteDTO {
    @JsonProperty("id")
    private String id;
    @JsonProperty("type")
    private String type;
    @JsonProperty("crId")
    private String crId;
    @JsonProperty("content")
    private String content;
    @JsonProperty("createdTime")
    private String createdTime;
    @JsonProperty("creatorId")
    private String creatorId;
    @JsonProperty("creatorName")
    private String creatorName;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

/**
 * 
 * @return
 *     The id
 */
@JsonProperty("id")
public String getId() {
    return id;
}

/**
 * 
 * @param id
 *     The id
 */
@JsonProperty("id")
public void setId(String id) {
    this.id = id;
}

public NoteDTO withId(String id) {
    this.id = id;
    return this;
}

/**
 * 
 * @return
 *     The type
 */
@JsonProperty("type")
public String getType() {
    return type;
}

/**
 * 
 * @param type
 *     The type
 */
@JsonProperty("type")
public void setType(String type) {
    this.type = type;
}

public NoteDTO withType(String type) {
    this.type = type;
    return this;
}

/**
 * 
 * @return
 *     The crId
 */
@JsonProperty("crId")
public String getCrId() {
    return crId;
}

/**
 * 
 * @param crId
 *     The crId
 */
@JsonProperty("crId")
public void setCrId(String crId) {
    this.crId = crId;
}

public NoteDTO withCrId(String crId) {
    this.crId = crId;
    return this;
}

/**
 * 
 * @return
 *     The content
 */
@JsonProperty("content")
public String getContent() {
    return content;
}

/**
 * 
 * @param content
 *     The content
 */
@JsonProperty("content")
public void setContent(String content) {
    this.content = content;
}

public NoteDTO withContent(String content) {
    this.content = content;
    return this;
}

/**
 * 
 * @return
 *     The createdTime
 */
@JsonProperty("createdTime")
public String getCreatedTime() {
    return createdTime;
}

/**
 * 
 * @param createdTime
 *     The createdTime
 */
@JsonProperty("createdTime")
public void setCreatedTime(String createdTime) {
    this.createdTime = createdTime;
}

public NoteDTO withCreatedTime(String createdTime) {
    this.createdTime = createdTime;
    return this;
}

/**
 * 
 * @return
 *     The creatorId
 */
@JsonProperty("creatorId")
public String getCreatorId() {
    return creatorId;
}

/**
 * 
 * @param creatorId
 *     The creatorId
 */
@JsonProperty("creatorId")
public void setCreatorId(String creatorId) {
    this.creatorId = creatorId;
}

public NoteDTO withCreatorId(String creatorId) {
    this.creatorId = creatorId;
    return this;
}

/**
 * 
 * @return
 *     The creatorName
 */
@JsonProperty("creatorName")
public String getCreatorName() {
    return creatorName;
}

/**
 * 
 * @param creatorName
 *     The creatorName
 */
@JsonProperty("creatorName")
public void setCreatorName(String creatorName) {
    this.creatorName = creatorName;
}

public NoteDTO withCreatorName(String creatorName) {
    this.creatorName = creatorName;
    return this;
}

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

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

public NoteDTO withAdditionalProperty(String name, Object value) {
    this.additionalProperties.put(name, value);
    return this;
}

}

The issue is when I return a Note object in resource method, the json response will be generated based on the jackson annotation in Note.Java and if a field’s value in Note is null, then the generated json won’t have that property which I need. How can I include all properties despite the value while converting java objects to json? I know the key is the annotation @JsonInclude, but it’s automatically generated by raml, how can I custom it?


#2

First question… why do you need the property if its null? One of the benefits of this is that by setting it to null it removes it from the response… lessening the amount of data returned. Typically, the less data you return, the better.

If you use Postman to make the request, you will see the elements of null missing. If you build a client that uses the same JSON pojo generated, they get a pojo back that would have null set for the elements not returned via JSON.

Who is the consumer of your API? Is it a web UI that uses the property names returned, even if null, to display in the UI?


#3

@Kevin_Duffey
Pl, refer below implementation details by which you can control the behavior of the Jackson Lib output.

  1. Define a class for the JacksonJsonMapper like
    public class JacksonJsonMapper extends ObjectMapper {

    public JacksonJsonMapper () {
    super();

     this.setSerializationInclusion(Inclusion.NON_NULL); //review & change it
    
     final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
     this.setDeserializationConfig(this.getDeserializationConfig().withAnnotationIntrospector(introspector));
     this.setSerializationConfig(this.getSerializationConfig().withAnnotationIntrospector(introspector));
     this.disable(Feature.FAIL_ON_EMPTY_BEANS);
     this.disable(Feature.WRITE_EMPTY_JSON_ARRAYS);
    

    }
    }

  2. Define a Bean for above Mapper class:
    <spring:bean class="com.myorgname.esb.json.JacksonJsonMapper " name=“JacksonMapper” />

  3. Use this bean to transform the object into the JSON using:
    <json:object-to-json-transformer doc:name=“Object to JSON” mapper-ref=“JacksonMapper” />
    HTH!