stoicflame / enunciate

Build-time enhancement tool for Java-based Web services projects
http://enunciate.webcohesion.com/
Other
481 stars 200 forks source link

Why not `integer` type? #813

Closed kkwansj closed 6 years ago

kkwansj commented 6 years ago

Hi!

Have question about Enunciate and the integer data type. When attempting to document API's that return JSON representation of the following Java object class:

public class Image implements Serializable {
    private static final long serialVersionUID = 1L;
    private int type = 0;   
    private String url = null;  
}

Enunciate 2.10.1 produces the following Model specification in documentation:

json_Image {
    type (number, optional): ,
    url (string, optional):
}

Here, the member variable type is described as number (float) type, instead of integer type as it is defined in source. Sure enough, upon inspection, the spec in swagger.json is generated as follows:

{
   "json_Image":{
      "type":"object",
      "title":"Image",
      "properties":{
         "url":{
            "description":"",
            "type":"string"
         },
         "type":{
            "description":"",
            "type":"number"
         }
      },
      "example":{
         "url":"...",
         "type":12345
      },
      "description":""
   }
}

So wanted to ask why are the int types being specified as number types, and how I might go about fixing this?

stoicflame commented 6 years ago

The reason is historical; JSON schema doesn't support integer as a data type, and the Swagger spec hasn't always supported integer. I'll track this as an enhancement request.

bbhavsar commented 6 years ago

+1. Is there a workaround for this till the issue is fixed in enunciate?

stoicflame commented 6 years ago

Enunciate 2.11 has been released.

bbhavsar commented 6 years ago

Updated to Enunciate 2.11.0

Following Java model class still produces "number" for id field in the swagger.json. Tried both boxed and unboxed Java primitives.

public class ApiCommand {
  private long id;

  /**
   * The command ID.
   */
  @XmlElement
  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }
}

generated swagger.json

    "ApiCommand" : {
      "type" : "object", 
      "title" : "ApiCommand",
          "properties" : {
            "id" : {
        "description" : "The command ID.",
        "type" : "number"
            },
stoicflame commented 6 years ago

That's not what I'm seeing:

  "definitions": {
    "json_ApiCommand": {
      "type": "object",
      "title": "ApiCommand",
      "properties": {
        "id": {
          "readOnly": false,
          "description": "",
          "type": "integer",
          "format": "int64"
        }
      },
      "example": {
        "id": 12345
      },
      "description": ""
    },

I even used your own class. Here's the diff I applied to enunciate-sample:

diff --git a/src/main/java/com/ifyouwannabecool/api/PersonaService.java b/src/main/java/com/ifyouwannabecool/api/PersonaService.java
index a1b238d..d3f126a 100644
--- a/src/main/java/com/ifyouwannabecool/api/PersonaService.java
+++ b/src/main/java/com/ifyouwannabecool/api/PersonaService.java
@@ -14,6 +14,7 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;

+import com.ifyouwannabecool.domain.persona.ApiCommand;
 import com.ifyouwannabecool.domain.persona.Persona;

 /**
@@ -33,6 +34,10 @@ public interface PersonaService
     @GET
     Persona readPersona(@PathParam("id") String personaId);

+    @Path("command")
+    @GET
+    ApiCommand getCommand();
+
     @Path("/{id}.json")
     @GET
     @Produces("application/json")
diff --git a/src/main/java/com/ifyouwannabecool/domain/persona/ApiCommand.java b/src/main/java/com/ifyouwannabecool/domain/persona/ApiCommand.java
index cbf1465..424e813 100644
--- a/src/main/java/com/ifyouwannabecool/domain/persona/ApiCommand.java
+++ b/src/main/java/com/ifyouwannabecool/domain/persona/ApiCommand.java
@@ -1,7 +1,22 @@
 package com.ifyouwannabecool.domain.persona;

+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
 /**
  *
  */
+@XmlRootElement
 public class ApiCommand {
+
+  private long id;
+
+  @XmlElement
+  public long getId() {
+    return id;
+  }
+
+  public void setId(long id) {
+    this.id = id;
+  }
 }
diff --git a/src/main/java/com/ifyouwannabecool/impl/PersonaServiceImpl.java b/src/main/java/com/ifyouwannabecool/impl/PersonaServiceImpl.java
index 72b8b7a..e8f1e61 100644
--- a/src/main/java/com/ifyouwannabecool/impl/PersonaServiceImpl.java
+++ b/src/main/java/com/ifyouwannabecool/impl/PersonaServiceImpl.java
@@ -11,6 +11,7 @@ import javax.ws.rs.Path;

 import com.ifyouwannabecool.api.PermissionDeniedException;
 import com.ifyouwannabecool.api.PersonaService;
+import com.ifyouwannabecool.domain.persona.ApiCommand;
 import com.ifyouwannabecool.domain.persona.Persona;

 /**
@@ -28,6 +29,11 @@ public class PersonaServiceImpl implements PersonaService
         return persona;
     }

+    @Override
+    public ApiCommand getCommand() {
+        return null;
+    }
+
     public Persona readPersonaJson()
     {
         final Persona persona = new Persona();
rbuddhisagar commented 6 years ago

I noticed Java autoboxed entities (Long, Double) are getting converted into a "number" instead of an "integer". Is there a setting for autoboxing compliancy so that a Long gets converted into an integer without a need to change the java code?

stoicflame commented 6 years ago

There's not an option for that, no. You're welcome to open another issue to track that.