<@UFXGUFPV5> it should be working fine. when you s...
# http4k
d
@RajanS it should be working fine. when you say "in the swagger" - do you mean the JSON doc (say the example section of the definition), or are you having problems with the actual marshaling of the service? A Gist showing what you're seeing would help to diagnose if there is a problem
r
In the autogenerated
swagger.json
doc
d
can you post the the swagger here?
👍 1
r
Copy code
{
  "swagger": "2.0",
  "info": {
    "title": "API",
    "version": "v2.0",
    "description": ""
  },
  "basePath": "/",
  "tags": [],
  "paths": {
    "/api/v2/api": {
      "get": {
        "tags": [
          ""
        ],
        "summary": "some desc",
        "operationId": "get",
        "produces": [
          "application/json"
        ],
        "consumes": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "header",
            "name": "Authorization",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "get a set of data",
            "schema": {
              "$ref": "#/definitions/object-31373813"
            }
          },
          "204": {
            "description": "not recognised",
            "schema": {}
          }
        },
        "security": [],
        "description": "some desc"
      }
    }
  },
  "securityDefinitions": {},
  "definitions": {
    "object-164926786": {
      "type": "object",
      "properties": {
        "consentType": {
          "type": "string",
          "example": "EMAIL"
        },
        "consentAllowed": {
          "type": "boolean",
          "example": true
        }
      }
    },
    "object2079760391": {
      "type": "object",
      "properties": {
        "entity": {
          "type": "string",
          "example": "sourceA"
        },
        "consents": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/object-164926786"
          }
        }
      }
    },
    "object-31373813": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "example": "id"
        },
        "permissions": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/object2079760391"
          }
        }
      }
    }
  }
}
d
Which JSON library are you using?
the reason you're getting this is because the non-auto marshalling doesn't discriminate for lists on various types of "object". If you use Jackson, you'll get a much better result
Jackson will automatically break down the schema based on Class model, instead of just being based on anonymous objects (which is what is happening above)
here's an example which will use the auto-marshalling:
Copy code
val contract = contract {
    renderer = OpenApi3(ApiInfo("My great API", "v1.0"), Jackson)
    descriptionPath = "/swagger.json"
    security = mySecurity
    routes += greetRoute()
    routes += echoRoute()
}
specifically
renderer = OpenApi3(ApiInfo("My great API", "v1.0"), Jackson)
r
com.fasterxml.jackson
and we using
OpenApi2
Copy code
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.MapperFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.joda.JodaModule
import com.fasterxml.jackson.module.kotlin.KotlinModule
import org.http4k.format.ConfigurableJackson

object Json: ConfigurableJackson(ObjectMapper()
        .registerModule(KotlinModule())
        .registerModule(JodaModule())
        .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
        .disableDefaultTyping()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false)
        .configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true)
        .configure(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS, true)
        .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)

)
d
aha - OpenApi2 doesn't support the full auto marshalling
r
Oh, is it much effort to move to OpenApi3?
d
No.
Replace OpenApi2 with OpenApi3
🙂
r
🙂
@dave Is there a way of having optional values? Is this something that’s changed in OpenApi3. When doing this:
Copy code
receiving(Body.auto<ObjectA>().toLens() to ObjectA(ObjectB(PHONE = true, POST = true, SMS = true)
I get the following error:
Copy code
org.http4k.contract.openapi.v3.NoFieldFound: Could not find phone in ObjectB(PHONE=true, EMAIL=null, POST=true, SMS=true)
However, it’s fine when we do:
Copy code
receiving(Body.auto<ObjectA>().toLens() to ObjectA(ObjectB())
Dataclass:
Copy code
@JsonInclude(Include.NON_NULL)
data class ObjectB(
        val PHONE: Boolean? = null,
        val EMAIL: Boolean? = null,
        val POST: Boolean? = null,
        val SMS: Boolean? = null
)
d
Optionals work fine - but Jackson doesn’t deal very well with capitals in field names. Think there’s something in the faq about it in the cookbook - you can annotate the data class to force the field name to be caps.
👍 1