Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic generation of DSL given a case class #356

Open
gaeljw opened this issue Jan 8, 2023 · 3 comments
Open

Automatic generation of DSL given a case class #356

gaeljw opened this issue Jan 8, 2023 · 3 comments
Labels
enhancement New feature or request

Comments

@gaeljw
Copy link
Collaborator

gaeljw commented Jan 8, 2023

In some simple cases, it would be nice to support automatic generation of a DSL given a case class. Similar to what the Kotlin implementation offers with basedOnRequiredConstructorFields.

Expected usage would be something like following:

case class MyModel(a: String, b: Int, c: NestedModel)
case class NestedModel(x: Seq[Long])

val dsl = DslJsonBodyBuilder.fromType[MyModel]
// Gives a LambdaDslJsonBody => Unit
// Same as what would be given to:
newJsonObject { rootObj =>
  rootObj.stringType("a")
  rootObj.integerType("b")
  rootObj.newObject("c") { o =>
    o.newArray("x") { a =>
      a.longType()
    }
  }
}

We could also provide a helper in ScalaDsl (#355 ):

newJsonObject[MyModel]

The generated DSL would be using matching types, not values.

To implement that, we will need to use TypeTag but this won't be available in Scala 3 (there are other alternatives in Scala 3). This would mean a different codebase for Scala 2 & Scala 3 which is perfectly possible but I believe the sbt structure does not allow it for now.

@gaeljw
Copy link
Collaborator Author

gaeljw commented Jan 8, 2023

Giving it a 2nd thought, maybe a simpler approach could be to expose a bodyForm(case class instance) method which would act similar to the existing body(...) but would take benefit of the JSON encoder provided by the user though it's library of choice (Circe, play JSON..) to generate a DSL given an actual JSON value.

This feels a bit like a hack though as we should not need a JSON library to generate a DSL from a case class and we would have to do the work once for each library.

On the other hand, it could be a simpler approach and it would reuse potentially custom encoders written by the user.

@jbwheatley
Copy link
Owner

is this not what we already provide with our body syntax?

A user can provide a case class and it will use e.g. a circe encoder to produce a DSL if using the circe import.

@gaeljw
Copy link
Collaborator Author

gaeljw commented Jan 18, 2023

Unfortunately no because the body syntax already provided generates a DSL with "value matching" whereas I'm looking for "type matching".

Actually the body[A : PactBodyJsonEncoder] method doesn't bring much value IMHO as the same could be achieved with body(myJsonLib.generateJsonString(instance)). For instance: https://github.com/jbwheatley/pact4s/blob/main/play-json/src/main/scala/pact4s/playjson/implicits.scala#L29

There's actually a PactDslJsonBodyEncoder which looks more like what I'd want but there's no body method to use it right? And anyway, it still defines a DSL with "value matching" like https://github.com/jbwheatley/pact4s/blob/main/play-json/src/main/scala/pact4s/playjson/JsonConversion.scala#L30, here we call stringValue but I'd want stringType.

@gaeljw gaeljw added the enhancement New feature or request label Feb 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants