From 8cdbee9fae6d587a24fc2ecb66db2da8010b0784 Mon Sep 17 00:00:00 2001 From: Andrew Kuhnhausen Date: Mon, 2 Apr 2018 09:52:11 -0700 Subject: [PATCH 1/3] Update swagger-parser to fix definition parse bug While parsing swagger with additionalProperties, not all definitions are resolved in swagger-parser < 1.0.34. (https://github.com/swagger-api/swagger-parser/pull/602) This brings us to the most recent version of swagger-parser on the 1.x line. Fixes: #40 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 7cf669d02a..e62bd95b7e 100644 --- a/build.sbt +++ b/build.sbt @@ -61,7 +61,7 @@ val codegenSettings = Seq( ), libraryDependencies ++= testDependencies ++ Seq( "org.scalameta" %% "scalameta" % "2.0.1" - , "io.swagger" % "swagger-parser" % "1.0.32" + , "io.swagger" % "swagger-parser" % "1.0.34" , "org.tpolecat" %% "atto-core" % "0.6.1" , "org.typelevel" %% "cats-core" % catsVersion , "org.typelevel" %% "cats-kernel" % catsVersion From e853cb9fc703d54be4403eb70cb8b36a99b16531 Mon Sep 17 00:00:00 2001 From: Andrew Kuhnhausen Date: Mon, 2 Apr 2018 10:40:29 -0700 Subject: [PATCH 2/3] Raise error when UntypedProperty occurs According to the Swagger spec (2.0) definitions (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#definitionsObject) can have null type via the JSON schema spec: https://tools.ietf.org/html/draft-zyp-json-schema-04#section-3.5 We don't currently have a mechanism to handle this case, so I am returning an error for now. --- .../src/main/scala/com/twilio/swagger/codegen/SwaggerUtil.scala | 2 ++ src/test/scala/generators/AkkaHttp/PropertyExtractors.scala | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/codegen/src/main/scala/com/twilio/swagger/codegen/SwaggerUtil.scala b/modules/codegen/src/main/scala/com/twilio/swagger/codegen/SwaggerUtil.scala index 1389ce3fb2..4ad752c6b4 100644 --- a/modules/codegen/src/main/scala/com/twilio/swagger/codegen/SwaggerUtil.scala +++ b/modules/codegen/src/main/scala/com/twilio/swagger/codegen/SwaggerUtil.scala @@ -295,6 +295,8 @@ object SwaggerUtil { Target.pure(Resolved(t"Double", None, Default(d).extract[Double].map(Lit.Double(_)))) case d: DecimalProperty => Target.pure(Resolved(t"BigDecimal", None, None)) + case u: UntypedProperty => + Target.error("FIXME: Got an untyped property, currently not supported") case p: AbstractProperty if p.getType.toLowerCase == "integer" => Target.pure(Resolved(t"BigInt", None, None)) case p: AbstractProperty if p.getType.toLowerCase == "number" => diff --git a/src/test/scala/generators/AkkaHttp/PropertyExtractors.scala b/src/test/scala/generators/AkkaHttp/PropertyExtractors.scala index e2bda6e663..9b1d2ce8aa 100644 --- a/src/test/scala/generators/AkkaHttp/PropertyExtractors.scala +++ b/src/test/scala/generators/AkkaHttp/PropertyExtractors.scala @@ -47,8 +47,6 @@ class PropertyExtractors extends FunSuite with Matchers { | format: double | number_property: | type: number - | property: - | default: "what" | object_property: | type: object |""".stripMargin From d5629eec594c720eda27fe83e1123cba99441662 Mon Sep 17 00:00:00 2001 From: Andrew Kuhnhausen Date: Wed, 4 Apr 2018 16:14:33 -0700 Subject: [PATCH 3/3] Fix untyped properties to Json per swagger spec swagger-codegen added UntypedProperty after version 1.0.32 which we didn't handle and this caused issues with code generation no longer properly reporting errors, just having a generic: Error: Unable to resolve type for null (null null null null) I took a look at the code that was added and what other implementations did: https://github.com/swagger-api/swagger-core#2507 For all the Scala code generators, they either returned Any (Akka, Scala, etc) or Object (finch). Though, how could we create an encoder/decoder for such an arbitrary type in any meaningful way? It appears in the case of additionalProperties and any other json schema proprty, all that is required is valid json. Since there is no actual type that we can infer from an untyped it makes sense to return the most specific type we can: Json. In this case, we are returning io.circe.Json --- .../com/twilio/swagger/codegen/SwaggerUtil.scala | 2 +- .../generators/AkkaHttp/PropertyExtractors.scala | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/modules/codegen/src/main/scala/com/twilio/swagger/codegen/SwaggerUtil.scala b/modules/codegen/src/main/scala/com/twilio/swagger/codegen/SwaggerUtil.scala index 4ad752c6b4..f48cc8ed78 100644 --- a/modules/codegen/src/main/scala/com/twilio/swagger/codegen/SwaggerUtil.scala +++ b/modules/codegen/src/main/scala/com/twilio/swagger/codegen/SwaggerUtil.scala @@ -296,7 +296,7 @@ object SwaggerUtil { case d: DecimalProperty => Target.pure(Resolved(t"BigDecimal", None, None)) case u: UntypedProperty => - Target.error("FIXME: Got an untyped property, currently not supported") + Target.pure(Resolved(t"io.circe.Json", None, None)) case p: AbstractProperty if p.getType.toLowerCase == "integer" => Target.pure(Resolved(t"BigInt", None, None)) case p: AbstractProperty if p.getType.toLowerCase == "number" => diff --git a/src/test/scala/generators/AkkaHttp/PropertyExtractors.scala b/src/test/scala/generators/AkkaHttp/PropertyExtractors.scala index 9b1d2ce8aa..020889fa61 100644 --- a/src/test/scala/generators/AkkaHttp/PropertyExtractors.scala +++ b/src/test/scala/generators/AkkaHttp/PropertyExtractors.scala @@ -47,6 +47,8 @@ class PropertyExtractors extends FunSuite with Matchers { | format: double | number_property: | type: number + | untyped_property: + | default: "what" | object_property: | type: object |""".stripMargin @@ -75,6 +77,7 @@ class PropertyExtractors extends FunSuite with Matchers { longProperty: Option[Long] = None, intProperty: Option[Int] = None, integerProperty: Option[BigInt] = None, floatProperty: Option[Float] = None, doubleProperty: Option[Double] = None, numberProperty: Option[BigDecimal] = None, + untypedProperty: Option[io.circe.Json] = None, objectProperty: Option[io.circe.Json] = None /*, refProperty: Option[ref_target_property] = None, refTargetProperty: Option[String] = None, arrayProperty: Option[IndexedSeq[ref_target_property]] = Option(IndexedSeq.empty) @@ -86,20 +89,20 @@ class PropertyExtractors extends FunSuite with Matchers { object Something { implicit val encodeSomething = { val readOnlyKeys = Set[String]() - Encoder.forProduct9( + Encoder.forProduct10( "boolean_value", "string_value", "long_property", "int_property", "integer_property", "float_property", - "double_property", "number_property", "object_property" + "double_property", "number_property", "untyped_property", "object_property" /*, "ref_property", "ref_target_property", "array_property" */ )( (o: Something) => ( o.booleanValue, o.stringValue, o.longProperty, o.intProperty, o.integerProperty, o.floatProperty, - o.doubleProperty, o.numberProperty, o.objectProperty + o.doubleProperty, o.numberProperty, o.untypedProperty, o.objectProperty /* , o.refProperty, o.refTargetProperty, o.arrayProperty */ ) ).mapJsonObject(_.filterKeys(key => !(readOnlyKeys contains key))) } - implicit val decodeSomething = Decoder.forProduct9( + implicit val decodeSomething = Decoder.forProduct10( "boolean_value", "string_value", "long_property", "int_property", "integer_property", "float_property", - "double_property", "number_property", "object_property" + "double_property", "number_property", "untyped_property", "object_property" /*, "ref_property", "ref_target_property", "array_property" */ )(Something.apply _) }