Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Scenario
- A spec model:
- ```
- "models":{
- "my_model": {
- "fields":[
- {"name": "a", "type": "int"}
- ]
- }
- }
- ```
- has previously generated code
- `case class MyModel (a: Integer)`
- We want to introduce a new field to our spec with minimal impact, including avoiding the impact of handling optionality/nullility to the degree possible.
- ```"models":{
- "my_model": {
- "fields":[
- {"name": "a", "type": "int"},
- {"name": "b", "type": "string", "default": "none"},
- ]
- }
- }```
- generates code
- ```case class MyModel (
- a: Integer,
- b: String
- )
- ...
- implicit def jsonReadsMyModel: play.api.libs.json.Reads[MyModel] = {
- (
- (__ \ "a").read[Integer] and
- (__ \ "b").read[String]
- )(MyModel.apply _)
- }
- ```
- along with client code that may look something like
- ```
- project io.example.clients
- case class MyModelForm(
- a: Integer,
- b: String = "none"
- )
- case object myModels{
- def put(myModel: MyModelForm): Unit
- }
- ```
- ## No problem
- A consumer of the API using a current or prior client to GET /my-model will receive the expected model.
- A consumer of the API using Postman, etc will receive the content they expect, plus an extra field b.
- A consumer of the API using the latest generated client to PUT to /my-model may omit b. The client will fill in the default value.
- ## Problem
- A consumer of the API using a prior model of client to PUT to /my-model finds that their client no longer works, as the client is not aware of the default.
- A consumer of the API using Postman etc to PUT to /my-model finds that old Requests no longer work.
- Models that were written (to a database, s3 etc) using a previous version of the spec will no longer be valid for the new spec. These will need to be updated without using generated tools.
- # Proposed Solution
- For older clients and existing models to support the new fields without rework, in the Scala generator we introduce application of the default to
- the model's unmarshalling implementation.
- ```implicit def jsonReadsMyModel: play.api.libs.json.Reads[MyModel] = {
- (
- (__ \ "a").read[Integer] and
- (__ \ "b").readWithDefault[String]("none")
- )(MyModel.apply _)
- }
- ```
- ## Unchanged
- A consumer of the API using a current or prior client to GET /my-model will receive the expected model.
- A consumer of the API using Postman, etc will receive the content they expect, plus an extra field b.
- A consumer of the API using the latest generated client to PUT to /my-model may omit b. The client will fill in the default value.
- ## Changed
- A consumer of the API using a prior model of client to PUT to /my-model finds that their client still works. The server introduces the default value when unmarshalling the request.
- A consumer of the API using Postman etc to PUT to /my-model finds that old Requests no longer work. The server introduces the default value when unmarshalling the request.
- Models that were written (to a database, s3 etc) using a previous version of the spec remain valid. Defaults will be introduced on unmarshalling.
Add Comment
Please, Sign In to add comment