Argus icon indicating copy to clipboard operation
Argus copied to clipboard

Eliminate intermediary "*Union" wrappers for object-typed oneOf traits

Open marcprux opened this issue 7 years ago • 1 comments

The following schema:

{
  "$ref": "#/definitions/FooBar",
  "definitions": {
    "FooBar": {
      "oneOf": [
        { "$ref": "#/definitions/Foo" },
        { "$ref": "#/definitions/Bar" }
      ]
    },
    "Foo": {
      "type": "object",
      "properties": {
        "foo": {
          "type": "string"
        }
      }
    },
    "Bar": {
      "type": "object",
      "properties": {
        "bar": {
          "type": "integer"
        }
      }
    }
  }
}

will yield this:

sealed trait FooBarUnion
case class FooBarFoo(x: Foo) extends FooBarUnion
case class FooBarBar(x: Bar) extends FooBarUnion
case class Foo(foo: Option[String] = None)
case class Bar(bar: Option[Int] = None)

It would be nice if the intermediary wrappers could be eliminated and this could be simplified to:

sealed trait FooBarUnion
case class Foo(foo: Option[String] = None) extends FooBarUnion
case class Bar(bar: Option[Int] = None) extends FooBarUnion

marcprux avatar Sep 21 '17 19:09 marcprux

An alternative (and simpler) approach could be to instead generate implicit converter functions between the union case class and the wrapped type. E.g.:

sealed trait FooBarUnion

case class FooBarFoo(x: Foo) extends FooBarUnion
implicit def ToFooBarFoo(x: Foo): FooBarFoo = FooBarFoo(x)
implicit def FromFooBarFoo(x: FooBarFoo): Foo = x.x

case class FooBarBar(x: Bar) extends FooBarUnion
implicit def ToFooBarBar(x: Bar): FooBarBar = FooBarBar(x)
implicit def FromFooBarBar(x: FooBarBar): Bar = x.x


case class Foo(foo: Option[String] = None)
case class Bar(bar: Option[Int] = None)

That way the client code won't usually need to be aware that there are wrapper types at all.

marcprux avatar Nov 15 '17 19:11 marcprux