ebowman / api-first-hand

API-First bootstrapping tool for building RESTful web services from a Swagger/OpenAPI spec
MIT License
142 stars 22 forks source link

No Json deserializer found for type #41

Closed eyasuyuki closed 7 years ago

eyasuyuki commented 7 years ago

I use this swagger spec.

swagger: "2.0"
info:
  version: 1.0.0
  title: example
basePath: /v1
schemes:
  - http
consumes:
  - application/json
produces:
  - application/json
paths:
  /user:
    get:
      summary: List all users
      operationId: listUser
      tags:
        - user
      responses:
        "200":
          description: An paged array of users
          headers:
            x-next:
              type: string
              description: A link to the next page of responses
          schema:
            type: array
            items:
              $ref: '#/definitions/User'
        default:
          description: unexpected error
          schema:
            $ref: '#/definitions/Error'
    post:
      summary: Create a User
      operationId: createUser
      tags:
        - user
      parameters:
        - name: name
          in: query
          type: string
          required: true
      responses:
        "200":
          description: created User
          schema:
            $ref: '#/definitions/User'
        default:
          description: unexpected error
          schema:
            $ref: '#/definitions/Error'
  /user/{id}:
    get:
      summary: Info for a specific pet
      operationId: showUserById
      tags:
        - user
      parameters:
        - name: id
          in: path
          required: true
          description: The id of the user to retrieve
          type: integer
      responses:
        "200":
          description: Expected response to a valid request
          schema:
            $ref: '#/definitions/User'
        default:
          description: unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      summary: Modify user
      operationId: putUser
      tags:
        - user
      parameters:
        - name: id
          in: path
          required: true
          description: User id
          type: integer
        - name: body
          in: body
          required: true
          schema:
            $ref: '#/definitions/User'
      responses:
        "200":
          description: User modified
          schema:
            $ref: '#/definitions/User'
        default:
          description: unexpetded error
          schema:
            $ref: '#/definitions/Error'
definitions:
  User:
    properties:
      id:
        type: integer
        format: int64
      name:
        type: string
      money:
        type: object
        allOf:
          - $ref: '#/definitions/Money'
  Money:
    properties:
      id:
        type: integer
        format: int64
      userId:
        type: integer
        format: int64
      amount:
        type: number
      createDate:
        type: string
        format: date-time
  Error:
    required:
      - code
      - message
    properties:
      code:
        type: integer
        format: int32
      message:
        type: string

I got these error.

play.sbt.PlayExceptions$CompilationException: Compilation error[No Json deserializer found for type example.yaml.UserMoney. Try to implement an implicit Reads or Format for this type.]
    at play.sbt.PlayExceptions$CompilationException$.apply(PlayExceptions.scala:27)
    at play.sbt.PlayExceptions$CompilationException$.apply(PlayExceptions.scala:27)
    at scala.Option.map(Option.scala:145)
    at play.sbt.run.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:49)
    at play.sbt.run.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:44)
    at scala.Option.map(Option.scala:145)
    at play.sbt.run.PlayReload$.taskFailureHandler(PlayReload.scala:44)
    at play.sbt.run.PlayReload$.compileFailure(PlayReload.scala:40)
    at play.sbt.run.PlayReload$$anonfun$compile$1.apply(PlayReload.scala:17)
    at play.sbt.run.PlayReload$$anonfun$compile$1.apply(PlayReload.scala:17)

project/plugins.sbt

resolvers += Resolver.url("sbt-plugins", url("http://dl.bintray.com/zalando/sbt-plugins"))(Resolver.ivyStylePatterns)

resolvers += "zalando-bintray"  at "https://dl.bintray.com/zalando/maven"

resolvers += "scalaz-bintray"   at "http://dl.bintray.com/scalaz/releases"

addSbtPlugin("com.typesafe.play" % "sbt-plugin"       % "2.5.4")

addSbtPlugin("de.zalando" % "sbt-api-first-hand" % "0.2.0")
eyasuyuki commented 7 years ago

I re-write a property 'money' from:

      money:
        type: object
        allOf:
          - $ref: '#/definitions/Money'

To:

      money:
        $ref: '#/definitions/Money'

Then I had no errors.

But I want to add this property to vendor extension property like below:

      money:
        x-foo: true
        type: object
        allOf:
          - $ref: '#/definitions/Money'

c.f.) https://github.com/OAI/OpenAPI-Specification/issues/556

Is this same issue of #23 ?

slavaschmidt commented 7 years ago

@eyasuyuki hey, thanks for the bug report! I think this is more related to the #39

slavaschmidt commented 7 years ago

Failing Reads:

object BodyReads extends MissingDefaultReads {
        implicit val MoneyReads: Reads[Money] = (
            (JsPath \ "id").readNullable[Long] and (JsPath \ "userId").readNullable[Long] and (JsPath \ "amount").readNullable[BigDecimal] and (JsPath \ "createDate").readNullable[ZonedDateTime]
        )(Money.apply _)
        implicit val UserReads: Reads[User] = (
            (JsPath \ "id").readNullable[Long] and (JsPath \ "name").readNullable[String] and (JsPath \ "money").read[UserMoney]
        )(User.apply _)
    }
slavaschmidt commented 7 years ago

Resolved in https://github.com/zalando/api-first-hand/pull/76