@@ -32,7 +32,7 @@ sealed trait {{classname}} {
3232sealed trait { {classname} }
3333{ {/vendorExtensions.x-hasParentProps} }
3434
35- { {! Generate inline case classes for oneOf members } }
35+ { {! Generate inline case classes for exclusive oneOf members } }
3636{ {#vendorExtensions.x-oneOfMembers} }
3737case class { {classname} }(
3838 { {#allVars} }
@@ -58,9 +58,15 @@ object {{classname}} {
5858
5959{ {/vendorExtensions.x-oneOfMembers} }
6060object { {classname} } {
61+ {{! Generate wrapper case classes for shared oneOf members } }
62+ { {#vendorExtensions.x-wrappedOneOfMembers} }
63+ case class { {wrapperClassname} }(value: { {classname} }) extends { {parentClassname} }
64+ { {/vendorExtensions.x-wrappedOneOfMembers} }
65+
6166{ {#json4s} }
6267 import org.json4s._
6368
69+ { {^vendorExtensions.x-hasWrappedOneOfMembers} }
6470{ {^vendorExtensions.x-use-discr} }
6571 // oneOf without discriminator - json4s custom serializer
6672 implicit object { {classname} }Serializer extends Serializer[{ {classname} }] {
@@ -103,8 +109,72 @@ object {{classname}} {
103109 }
104110 }
105111{ {/vendorExtensions.x-use-discr} }
112+ { {/vendorExtensions.x-hasWrappedOneOfMembers} }
113+ { {#vendorExtensions.x-hasWrappedOneOfMembers} }
114+ { {^vendorExtensions.x-use-discr} }
115+ // oneOf without discriminator - json4s custom serializer (with wrapper composition)
116+ implicit object { {classname} }Serializer extends Serializer[{ {classname} }] {
117+ private def tryDeserialize(json: JValue)(implicit format: Formats): Option[{{classname} }] = {
118+ {{#vendorExtensions.x-oneOfMembers} }
119+ scala.util.Try(Extraction.extract[{ {classname} }](json)).toOption match {
120+ case Some(x) => return Some(x)
121+ case None =>
122+ }
123+ { {/vendorExtensions.x-oneOfMembers} }
124+ { {#vendorExtensions.x-wrappedOneOfMembers} }
125+ scala.util.Try(Extraction.extract[{ {classname} }](json)).toOption match {
126+ case Some(x) => return Some({{wrapperClassname} }(x))
127+ case None =>
128+ }
129+ { {/vendorExtensions.x-wrappedOneOfMembers} }
130+ None
131+ }
132+
133+ def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), { {classname} }] = {
134+ case (TypeInfo(clazz, _), json) if classOf[{{classname} }].isAssignableFrom(clazz) =>
135+ tryDeserialize(json).getOrElse(throw new MappingException(s"Can't convert $json to { {classname} }"))
136+ }
137+
138+ def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
139+ {{#vendorExtensions.x-oneOfMembers} }
140+ case x: { {classname} } => Extraction.decompose(x)
141+ { {/vendorExtensions.x-oneOfMembers} }
142+ { {#vendorExtensions.x-wrappedOneOfMembers} }
143+ case { {wrapperClassname} }(v) => Extraction.decompose(v)
144+ { {/vendorExtensions.x-wrappedOneOfMembers} }
145+ }
146+ }
147+ { {/vendorExtensions.x-use-discr} }
148+ { {#vendorExtensions.x-use-discr} }
149+ // oneOf with discriminator (with wrapper composition)
150+ implicit object { {classname} }Serializer extends Serializer[{ {classname} }] {
151+ def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), {{classname} }] = {
152+ case (TypeInfo(clazz, _), json) if classOf[{{classname} }].isAssignableFrom(clazz) =>
153+ (json \ "{ {discriminator.propertyName} }") match {
154+ {{#vendorExtensions.x-oneOfMembers} }
155+ case JString("{ {vendorExtensions.x-discriminator-value} }") => Extraction.extract[{ {classname} }](json)
156+ { {/vendorExtensions.x-oneOfMembers} }
157+ { {#vendorExtensions.x-wrappedOneOfMembers} }
158+ case JString("{ {discriminatorValue} }") => { {wrapperClassname} }(Extraction.extract[{ {classname} }](json))
159+ { {/vendorExtensions.x-wrappedOneOfMembers} }
160+ case _ => throw new MappingException(s"Unknown discriminator value in $json")
161+ }
162+ }
163+
164+ def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
165+ {{#vendorExtensions.x-oneOfMembers} }
166+ case x: { {classname} } => Extraction.decompose(x).merge(JObject("{ {discriminator.propertyName} }" -> JString("{ {vendorExtensions.x-discriminator-value} }")))
167+ { {/vendorExtensions.x-oneOfMembers} }
168+ { {#vendorExtensions.x-wrappedOneOfMembers} }
169+ case { {wrapperClassname} }(v) => Extraction.decompose(v).merge(JObject("{ {discriminator.propertyName} }" -> JString("{ {discriminatorValue} }")))
170+ { {/vendorExtensions.x-wrappedOneOfMembers} }
171+ }
172+ }
173+ { {/vendorExtensions.x-use-discr} }
174+ { {/vendorExtensions.x-hasWrappedOneOfMembers} }
106175{ {/json4s} }
107176{ {#circe} }
177+ { {^vendorExtensions.x-hasWrappedOneOfMembers} }
108178{ {^vendorExtensions.x-use-discr} }
109179 // oneOf without discriminator - using semiauto derivation
110180 import io.circe.{ Encoder, Decoder}
@@ -131,6 +201,54 @@ object {{classname}} {
131201 implicit val encoder: Encoder[{ {classname} }] = deriveConfiguredEncoder
132202 implicit val decoder: Decoder[{ {classname} }] = deriveConfiguredDecoder
133203{ {/vendorExtensions.x-use-discr} }
204+ { {/vendorExtensions.x-hasWrappedOneOfMembers} }
205+ { {#vendorExtensions.x-hasWrappedOneOfMembers} }
206+ import io.circe.{ Encoder, Decoder}
207+ import io.circe.syntax._
208+ { {^vendorExtensions.x-use-discr} }
209+ // oneOf without discriminator (with wrapper composition)
210+ implicit val encoder: Encoder[{ {classname} }] = Encoder.instance {
211+ {{#vendorExtensions.x-oneOfMembers} }
212+ case x: { {classname} } => { {classname} }.encoder(x)
213+ { {/vendorExtensions.x-oneOfMembers} }
214+ { {#vendorExtensions.x-wrappedOneOfMembers} }
215+ case { {wrapperClassname} }(v) => Encoder[{ {classname} }].apply(v)
216+ { {/vendorExtensions.x-wrappedOneOfMembers} }
217+ }
218+
219+ implicit val decoder: Decoder[{ {classname} }] = List[Decoder[{ {classname} }]](
220+ { {#vendorExtensions.x-oneOfMembers} }
221+ Decoder[{ {classname} }].widen,
222+ { {/vendorExtensions.x-oneOfMembers} }
223+ { {#vendorExtensions.x-wrappedOneOfMembers} }
224+ Decoder[{ {classname} }].map({ {wrapperClassname} }.apply),
225+ { {/vendorExtensions.x-wrappedOneOfMembers} }
226+ ).reduceLeft(_ or _)
227+ { {/vendorExtensions.x-use-discr} }
228+ { {#vendorExtensions.x-use-discr} }
229+ // oneOf with discriminator (with wrapper composition)
230+ implicit val encoder: Encoder[{ {classname} }] = Encoder.instance {
231+ {{#vendorExtensions.x-oneOfMembers} }
232+ case x: { {classname} } => { {classname} }.encoder(x)
233+ { {/vendorExtensions.x-oneOfMembers} }
234+ { {#vendorExtensions.x-wrappedOneOfMembers} }
235+ case { {wrapperClassname} }(v) => Encoder[{ {classname} }].apply(v)
236+ { {/vendorExtensions.x-wrappedOneOfMembers} }
237+ }
238+
239+ implicit val decoder: Decoder[{ {classname} }] = Decoder.instance { c =>
240+ c.get[String](" {{discriminator.propertyName}}" ).flatMap {
241+ {{#vendorExtensions.x-oneOfMembers} }
242+ case "{ {vendorExtensions.x-discriminator-value} }" => c.as[{ {classname} }]({ {classname} }.decoder).map(x => x: { {parentClassname} })
243+ { {/vendorExtensions.x-oneOfMembers} }
244+ { {#vendorExtensions.x-wrappedOneOfMembers} }
245+ case "{ {discriminatorValue} }" => c.as[{ {classname} }]({ {classname} }.decoder).map({ {wrapperClassname} }.apply)
246+ { {/vendorExtensions.x-wrappedOneOfMembers} }
247+ case other => Left(io.circe.DecodingFailure(s"Unknown { {discriminator.propertyName} }: $$other", c.history))
248+ }
249+ }
250+ { {/vendorExtensions.x-use-discr} }
251+ { {/vendorExtensions.x-hasWrappedOneOfMembers} }
134252{ {/circe} }
135253}
136254{ {/vendorExtensions.x-isSealedTrait} }
0 commit comments